Roll src/third_party/skia e784db4:fa5e68e
[chromium-blink-merge.git] / cc / resources / resource_provider_unittest.cc
blob136855847db72d82a8ea2ccd33be7fb3b16a3daa
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>
11 #include "base/bind.h"
12 #include "base/containers/hash_tables.h"
13 #include "base/logging.h"
14 #include "base/memory/ref_counted.h"
15 #include "cc/base/scoped_ptr_deque.h"
16 #include "cc/output/output_surface.h"
17 #include "cc/resources/returned_resource.h"
18 #include "cc/resources/shared_bitmap_manager.h"
19 #include "cc/resources/single_release_callback.h"
20 #include "cc/test/fake_output_surface.h"
21 #include "cc/test/fake_output_surface_client.h"
22 #include "cc/test/test_gpu_memory_buffer_manager.h"
23 #include "cc/test/test_shared_bitmap_manager.h"
24 #include "cc/test/test_texture.h"
25 #include "cc/test/test_web_graphics_context_3d.h"
26 #include "cc/trees/blocking_task_runner.h"
27 #include "gpu/GLES2/gl2extchromium.h"
28 #include "testing/gmock/include/gmock/gmock.h"
29 #include "testing/gtest/include/gtest/gtest.h"
30 #include "third_party/khronos/GLES2/gl2.h"
31 #include "third_party/khronos/GLES2/gl2ext.h"
32 #include "ui/gfx/geometry/rect.h"
33 #include "ui/gfx/gpu_memory_buffer.h"
35 using testing::Mock;
36 using testing::NiceMock;
37 using testing::Return;
38 using testing::SetArgPointee;
39 using testing::StrictMock;
40 using testing::_;
42 namespace cc {
43 namespace {
45 static void EmptyReleaseCallback(uint32 sync_point,
46 bool lost_resource,
47 BlockingTaskRunner* main_thread_task_runner) {
50 static void ReleaseCallback(
51 uint32* release_sync_point,
52 bool* release_lost_resource,
53 BlockingTaskRunner** release_main_thread_task_runner,
54 uint32 sync_point,
55 bool lost_resource,
56 BlockingTaskRunner* main_thread_task_runner) {
57 *release_sync_point = sync_point;
58 *release_lost_resource = lost_resource;
59 *release_main_thread_task_runner = main_thread_task_runner;
62 static void SharedBitmapReleaseCallback(
63 scoped_ptr<SharedBitmap> bitmap,
64 uint32 sync_point,
65 bool lost_resource,
66 BlockingTaskRunner* main_thread_task_runner) {
69 static void ReleaseSharedBitmapCallback(
70 scoped_ptr<SharedBitmap> shared_bitmap,
71 bool* release_called,
72 uint32* release_sync_point,
73 bool* lost_resource_result,
74 uint32 sync_point,
75 bool lost_resource,
76 BlockingTaskRunner* main_thread_task_runner) {
77 *release_called = true;
78 *release_sync_point = sync_point;
79 *lost_resource_result = lost_resource;
82 static scoped_ptr<SharedBitmap> CreateAndFillSharedBitmap(
83 SharedBitmapManager* manager,
84 const gfx::Size& size,
85 uint32_t value) {
86 scoped_ptr<SharedBitmap> shared_bitmap = manager->AllocateSharedBitmap(size);
87 CHECK(shared_bitmap);
88 uint32_t* pixels = reinterpret_cast<uint32_t*>(shared_bitmap->pixels());
89 CHECK(pixels);
90 std::fill_n(pixels, size.GetArea(), value);
91 return shared_bitmap.Pass();
94 class TextureStateTrackingContext : public TestWebGraphicsContext3D {
95 public:
96 MOCK_METHOD2(bindTexture, void(GLenum target, GLuint texture));
97 MOCK_METHOD3(texParameteri, void(GLenum target, GLenum pname, GLint param));
98 MOCK_METHOD1(waitSyncPoint, void(GLuint sync_point));
99 MOCK_METHOD0(insertSyncPoint, GLuint(void));
100 MOCK_METHOD3(produceTextureDirectCHROMIUM,
101 void(GLuint texture, GLenum target, const GLbyte* mailbox));
102 MOCK_METHOD2(createAndConsumeTextureCHROMIUM,
103 unsigned(GLenum target, const GLbyte* mailbox));
105 // Force all textures to be consecutive numbers starting at "1",
106 // so we easily can test for them.
107 GLuint NextTextureId() override {
108 base::AutoLock lock(namespace_->lock);
109 return namespace_->next_texture_id++;
111 void RetireTextureId(GLuint) override {}
114 // Shared data between multiple ResourceProviderContext. This contains mailbox
115 // contents as well as information about sync points.
116 class ContextSharedData {
117 public:
118 static scoped_ptr<ContextSharedData> Create() {
119 return make_scoped_ptr(new ContextSharedData());
122 uint32 InsertSyncPoint() { return next_sync_point_++; }
124 void GenMailbox(GLbyte* mailbox) {
125 memset(mailbox, 0, GL_MAILBOX_SIZE_CHROMIUM);
126 memcpy(mailbox, &next_mailbox_, sizeof(next_mailbox_));
127 ++next_mailbox_;
130 void ProduceTexture(const GLbyte* mailbox_name,
131 uint32 sync_point,
132 scoped_refptr<TestTexture> texture) {
133 unsigned mailbox = 0;
134 memcpy(&mailbox, mailbox_name, sizeof(mailbox));
135 ASSERT_TRUE(mailbox && mailbox < next_mailbox_);
136 textures_[mailbox] = texture;
137 ASSERT_LT(sync_point_for_mailbox_[mailbox], sync_point);
138 sync_point_for_mailbox_[mailbox] = sync_point;
141 scoped_refptr<TestTexture> ConsumeTexture(const GLbyte* mailbox_name,
142 uint32 sync_point) {
143 unsigned mailbox = 0;
144 memcpy(&mailbox, mailbox_name, sizeof(mailbox));
145 DCHECK(mailbox && mailbox < next_mailbox_);
147 // If the latest sync point the context has waited on is before the sync
148 // point for when the mailbox was set, pretend we never saw that
149 // ProduceTexture.
150 if (sync_point_for_mailbox_[mailbox] > sync_point) {
151 NOTREACHED();
152 return scoped_refptr<TestTexture>();
154 return textures_[mailbox];
157 private:
158 ContextSharedData() : next_sync_point_(1), next_mailbox_(1) {}
160 uint32 next_sync_point_;
161 unsigned next_mailbox_;
162 typedef base::hash_map<unsigned, scoped_refptr<TestTexture>> TextureMap;
163 TextureMap textures_;
164 base::hash_map<unsigned, uint32> sync_point_for_mailbox_;
167 class ResourceProviderContext : public TestWebGraphicsContext3D {
168 public:
169 static scoped_ptr<ResourceProviderContext> Create(
170 ContextSharedData* shared_data) {
171 return make_scoped_ptr(new ResourceProviderContext(shared_data));
174 GLuint insertSyncPoint() override {
175 uint32 sync_point = shared_data_->InsertSyncPoint();
176 // Commit the produceTextureCHROMIUM calls at this point, so that
177 // they're associated with the sync point.
178 for (PendingProduceTextureList::iterator it =
179 pending_produce_textures_.begin();
180 it != pending_produce_textures_.end();
181 ++it) {
182 shared_data_->ProduceTexture(
183 (*it)->mailbox, sync_point, (*it)->texture);
185 pending_produce_textures_.clear();
186 return sync_point;
189 void waitSyncPoint(GLuint sync_point) override {
190 last_waited_sync_point_ = std::max(sync_point, last_waited_sync_point_);
193 unsigned last_waited_sync_point() const { return last_waited_sync_point_; }
195 void texStorage2DEXT(GLenum target,
196 GLint levels,
197 GLuint internalformat,
198 GLint width,
199 GLint height) override {
200 CheckTextureIsBound(target);
201 ASSERT_EQ(static_cast<unsigned>(GL_TEXTURE_2D), target);
202 ASSERT_EQ(1, levels);
203 GLenum format = GL_RGBA;
204 switch (internalformat) {
205 case GL_RGBA8_OES:
206 break;
207 case GL_BGRA8_EXT:
208 format = GL_BGRA_EXT;
209 break;
210 default:
211 NOTREACHED();
213 AllocateTexture(gfx::Size(width, height), format);
216 void texImage2D(GLenum target,
217 GLint level,
218 GLenum internalformat,
219 GLsizei width,
220 GLsizei height,
221 GLint border,
222 GLenum format,
223 GLenum type,
224 const void* pixels) override {
225 CheckTextureIsBound(target);
226 ASSERT_EQ(static_cast<unsigned>(GL_TEXTURE_2D), target);
227 ASSERT_FALSE(level);
228 ASSERT_EQ(internalformat, format);
229 ASSERT_FALSE(border);
230 ASSERT_EQ(static_cast<unsigned>(GL_UNSIGNED_BYTE), type);
231 AllocateTexture(gfx::Size(width, height), format);
232 if (pixels)
233 SetPixels(0, 0, width, height, pixels);
236 void texSubImage2D(GLenum target,
237 GLint level,
238 GLint xoffset,
239 GLint yoffset,
240 GLsizei width,
241 GLsizei height,
242 GLenum format,
243 GLenum type,
244 const void* pixels) override {
245 CheckTextureIsBound(target);
246 ASSERT_EQ(static_cast<unsigned>(GL_TEXTURE_2D), target);
247 ASSERT_FALSE(level);
248 ASSERT_EQ(static_cast<unsigned>(GL_UNSIGNED_BYTE), type);
250 base::AutoLock lock_for_texture_access(namespace_->lock);
251 ASSERT_EQ(GLDataFormat(BoundTexture(target)->format), format);
253 ASSERT_TRUE(pixels);
254 SetPixels(xoffset, yoffset, width, height, pixels);
257 void genMailboxCHROMIUM(GLbyte* mailbox) override {
258 return shared_data_->GenMailbox(mailbox);
261 void produceTextureDirectCHROMIUM(GLuint texture,
262 GLenum target,
263 const GLbyte* mailbox) override {
264 // Delay moving the texture into the mailbox until the next
265 // InsertSyncPoint, so that it is not visible to other contexts that
266 // haven't waited on that sync point.
267 scoped_ptr<PendingProduceTexture> pending(new PendingProduceTexture);
268 memcpy(pending->mailbox, mailbox, sizeof(pending->mailbox));
269 base::AutoLock lock_for_texture_access(namespace_->lock);
270 pending->texture = UnboundTexture(texture);
271 pending_produce_textures_.push_back(pending.Pass());
274 GLuint createAndConsumeTextureCHROMIUM(GLenum target,
275 const GLbyte* mailbox) override {
276 GLuint texture_id = createTexture();
277 base::AutoLock lock_for_texture_access(namespace_->lock);
278 scoped_refptr<TestTexture> texture =
279 shared_data_->ConsumeTexture(mailbox, last_waited_sync_point_);
280 namespace_->textures.Replace(texture_id, texture);
281 return texture_id;
284 void GetPixels(const gfx::Size& size,
285 ResourceFormat format,
286 uint8_t* pixels) {
287 CheckTextureIsBound(GL_TEXTURE_2D);
288 base::AutoLock lock_for_texture_access(namespace_->lock);
289 scoped_refptr<TestTexture> texture = BoundTexture(GL_TEXTURE_2D);
290 ASSERT_EQ(texture->size, size);
291 ASSERT_EQ(texture->format, format);
292 memcpy(pixels, texture->data.get(), TextureSizeBytes(size, format));
295 protected:
296 explicit ResourceProviderContext(ContextSharedData* shared_data)
297 : shared_data_(shared_data),
298 last_waited_sync_point_(0) {}
300 private:
301 void AllocateTexture(const gfx::Size& size, GLenum format) {
302 CheckTextureIsBound(GL_TEXTURE_2D);
303 ResourceFormat texture_format = RGBA_8888;
304 switch (format) {
305 case GL_RGBA:
306 texture_format = RGBA_8888;
307 break;
308 case GL_BGRA_EXT:
309 texture_format = BGRA_8888;
310 break;
312 base::AutoLock lock_for_texture_access(namespace_->lock);
313 BoundTexture(GL_TEXTURE_2D)->Reallocate(size, texture_format);
316 void SetPixels(int xoffset,
317 int yoffset,
318 int width,
319 int height,
320 const void* pixels) {
321 CheckTextureIsBound(GL_TEXTURE_2D);
322 base::AutoLock lock_for_texture_access(namespace_->lock);
323 scoped_refptr<TestTexture> texture = BoundTexture(GL_TEXTURE_2D);
324 ASSERT_TRUE(texture->data.get());
325 ASSERT_TRUE(xoffset >= 0 && xoffset + width <= texture->size.width());
326 ASSERT_TRUE(yoffset >= 0 && yoffset + height <= texture->size.height());
327 ASSERT_TRUE(pixels);
328 size_t in_pitch = TextureSizeBytes(gfx::Size(width, 1), texture->format);
329 size_t out_pitch =
330 TextureSizeBytes(gfx::Size(texture->size.width(), 1), texture->format);
331 uint8_t* dest = texture->data.get() + yoffset * out_pitch +
332 TextureSizeBytes(gfx::Size(xoffset, 1), texture->format);
333 const uint8_t* src = static_cast<const uint8_t*>(pixels);
334 for (int i = 0; i < height; ++i) {
335 memcpy(dest, src, in_pitch);
336 dest += out_pitch;
337 src += in_pitch;
341 struct PendingProduceTexture {
342 GLbyte mailbox[GL_MAILBOX_SIZE_CHROMIUM];
343 scoped_refptr<TestTexture> texture;
345 typedef ScopedPtrDeque<PendingProduceTexture> PendingProduceTextureList;
346 ContextSharedData* shared_data_;
347 GLuint last_waited_sync_point_;
348 PendingProduceTextureList pending_produce_textures_;
351 void GetResourcePixels(ResourceProvider* resource_provider,
352 ResourceProviderContext* context,
353 ResourceId id,
354 const gfx::Size& size,
355 ResourceFormat format,
356 uint8_t* pixels) {
357 resource_provider->WaitSyncPointIfNeeded(id);
358 switch (resource_provider->default_resource_type()) {
359 case ResourceProvider::RESOURCE_TYPE_GL_TEXTURE: {
360 ResourceProvider::ScopedReadLockGL lock_gl(resource_provider, id);
361 ASSERT_NE(0U, lock_gl.texture_id());
362 context->bindTexture(GL_TEXTURE_2D, lock_gl.texture_id());
363 context->GetPixels(size, format, pixels);
364 break;
366 case ResourceProvider::RESOURCE_TYPE_BITMAP: {
367 ResourceProvider::ScopedReadLockSoftware lock_software(resource_provider,
368 id);
369 memcpy(pixels,
370 lock_software.sk_bitmap()->getPixels(),
371 lock_software.sk_bitmap()->getSize());
372 break;
377 class ResourceProviderTest
378 : public testing::TestWithParam<ResourceProvider::ResourceType> {
379 public:
380 explicit ResourceProviderTest(bool child_needs_sync_point)
381 : shared_data_(ContextSharedData::Create()),
382 context3d_(NULL),
383 child_context_(NULL),
384 main_thread_task_runner_(BlockingTaskRunner::Create(NULL)) {
385 switch (GetParam()) {
386 case ResourceProvider::RESOURCE_TYPE_GL_TEXTURE: {
387 scoped_ptr<ResourceProviderContext> context3d(
388 ResourceProviderContext::Create(shared_data_.get()));
389 context3d_ = context3d.get();
391 scoped_refptr<TestContextProvider> context_provider =
392 TestContextProvider::Create(context3d.Pass());
394 output_surface_ = FakeOutputSurface::Create3d(context_provider);
396 scoped_ptr<ResourceProviderContext> child_context_owned =
397 ResourceProviderContext::Create(shared_data_.get());
398 child_context_ = child_context_owned.get();
399 if (child_needs_sync_point) {
400 child_output_surface_ =
401 FakeOutputSurface::Create3d(child_context_owned.Pass());
402 } else {
403 child_output_surface_ = FakeOutputSurface::CreateNoRequireSyncPoint(
404 child_context_owned.Pass());
406 break;
408 case ResourceProvider::RESOURCE_TYPE_BITMAP:
409 output_surface_ = FakeOutputSurface::CreateSoftware(
410 make_scoped_ptr(new SoftwareOutputDevice));
411 child_output_surface_ = FakeOutputSurface::CreateSoftware(
412 make_scoped_ptr(new SoftwareOutputDevice));
413 break;
415 CHECK(output_surface_->BindToClient(&output_surface_client_));
416 CHECK(child_output_surface_->BindToClient(&child_output_surface_client_));
418 shared_bitmap_manager_.reset(new TestSharedBitmapManager);
419 gpu_memory_buffer_manager_.reset(new TestGpuMemoryBufferManager);
421 resource_provider_ = ResourceProvider::Create(
422 output_surface_.get(), shared_bitmap_manager_.get(),
423 gpu_memory_buffer_manager_.get(), main_thread_task_runner_.get(), 0,
424 false, 1, false);
425 child_resource_provider_ = ResourceProvider::Create(
426 child_output_surface_.get(), shared_bitmap_manager_.get(),
427 gpu_memory_buffer_manager_.get(), main_thread_task_runner_.get(), 0,
428 false, 1, false);
431 ResourceProviderTest() : ResourceProviderTest(true) {}
433 static void CollectResources(ReturnedResourceArray* array,
434 const ReturnedResourceArray& returned,
435 BlockingTaskRunner* main_thread_task_runner) {
436 array->insert(array->end(), returned.begin(), returned.end());
439 static ReturnCallback GetReturnCallback(ReturnedResourceArray* array) {
440 return base::Bind(&ResourceProviderTest::CollectResources, array);
443 static void SetResourceFilter(ResourceProvider* resource_provider,
444 ResourceId id,
445 GLenum filter) {
446 ResourceProvider::ScopedSamplerGL sampler(
447 resource_provider, id, GL_TEXTURE_2D, filter);
450 ResourceProviderContext* context() { return context3d_; }
452 ResourceId CreateChildMailbox(uint32* release_sync_point,
453 bool* lost_resource,
454 bool* release_called,
455 uint32* sync_point) {
456 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) {
457 unsigned texture = child_context_->createTexture();
458 gpu::Mailbox gpu_mailbox;
459 child_context_->genMailboxCHROMIUM(gpu_mailbox.name);
460 child_context_->produceTextureDirectCHROMIUM(texture, GL_TEXTURE_2D,
461 gpu_mailbox.name);
462 *sync_point = child_context_->insertSyncPoint();
463 EXPECT_LT(0u, *sync_point);
465 scoped_ptr<SharedBitmap> shared_bitmap;
466 scoped_ptr<SingleReleaseCallbackImpl> callback =
467 SingleReleaseCallbackImpl::Create(base::Bind(
468 ReleaseSharedBitmapCallback, base::Passed(&shared_bitmap),
469 release_called, release_sync_point, lost_resource));
470 return child_resource_provider_->CreateResourceFromTextureMailbox(
471 TextureMailbox(gpu_mailbox, GL_TEXTURE_2D, *sync_point),
472 callback.Pass());
473 } else {
474 gfx::Size size(64, 64);
475 scoped_ptr<SharedBitmap> shared_bitmap(
476 CreateAndFillSharedBitmap(shared_bitmap_manager_.get(), size, 0));
478 SharedBitmap* shared_bitmap_ptr = shared_bitmap.get();
479 scoped_ptr<SingleReleaseCallbackImpl> callback =
480 SingleReleaseCallbackImpl::Create(base::Bind(
481 ReleaseSharedBitmapCallback, base::Passed(&shared_bitmap),
482 release_called, release_sync_point, lost_resource));
483 return child_resource_provider_->CreateResourceFromTextureMailbox(
484 TextureMailbox(shared_bitmap_ptr, size), callback.Pass());
488 protected:
489 scoped_ptr<ContextSharedData> shared_data_;
490 ResourceProviderContext* context3d_;
491 ResourceProviderContext* child_context_;
492 FakeOutputSurfaceClient output_surface_client_;
493 FakeOutputSurfaceClient child_output_surface_client_;
494 scoped_ptr<OutputSurface> output_surface_;
495 scoped_ptr<OutputSurface> child_output_surface_;
496 scoped_ptr<BlockingTaskRunner> main_thread_task_runner_;
497 scoped_ptr<ResourceProvider> resource_provider_;
498 scoped_ptr<ResourceProvider> child_resource_provider_;
499 scoped_ptr<TestSharedBitmapManager> shared_bitmap_manager_;
500 scoped_ptr<TestGpuMemoryBufferManager> gpu_memory_buffer_manager_;
503 void CheckCreateResource(ResourceProvider::ResourceType expected_default_type,
504 ResourceProvider* resource_provider,
505 ResourceProviderContext* context) {
506 DCHECK_EQ(expected_default_type, resource_provider->default_resource_type());
508 gfx::Size size(1, 1);
509 ResourceFormat format = RGBA_8888;
510 size_t pixel_size = TextureSizeBytes(size, format);
511 ASSERT_EQ(4U, pixel_size);
513 ResourceId id = resource_provider->CreateResource(
514 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
515 EXPECT_EQ(1, static_cast<int>(resource_provider->num_resources()));
516 if (expected_default_type == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
517 EXPECT_EQ(0u, context->NumTextures());
519 uint8_t data[4] = { 1, 2, 3, 4 };
520 resource_provider->CopyToResource(id, data, size);
521 if (expected_default_type == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
522 EXPECT_EQ(1u, context->NumTextures());
524 uint8_t result[4] = { 0 };
525 GetResourcePixels(resource_provider, context, id, size, format, result);
526 EXPECT_EQ(0, memcmp(data, result, pixel_size));
528 resource_provider->DeleteResource(id);
529 EXPECT_EQ(0, static_cast<int>(resource_provider->num_resources()));
530 if (expected_default_type == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
531 EXPECT_EQ(0u, context->NumTextures());
534 TEST_P(ResourceProviderTest, Basic) {
535 CheckCreateResource(GetParam(), resource_provider_.get(), context());
538 TEST_P(ResourceProviderTest, SimpleUpload) {
539 gfx::Size size(2, 2);
540 ResourceFormat format = RGBA_8888;
541 size_t pixel_size = TextureSizeBytes(size, format);
542 ASSERT_EQ(16U, pixel_size);
544 ResourceId id = resource_provider_->CreateResource(
545 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
547 uint8_t image[16] = {0};
548 resource_provider_->CopyToResource(id, image, size);
550 uint8_t result[16] = {0};
551 uint8_t expected[16] = {0};
552 GetResourcePixels(resource_provider_.get(), context(), id, size, format,
553 result);
554 EXPECT_EQ(0, memcmp(expected, result, pixel_size));
557 for (uint8_t i = 0; i < pixel_size; ++i)
558 image[i] = i;
559 resource_provider_->CopyToResource(id, image, size);
561 uint8_t result[16] = {0};
562 uint8_t expected[16] = {
563 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
564 GetResourcePixels(resource_provider_.get(), context(), id, size, format,
565 result);
566 EXPECT_EQ(0, memcmp(expected, result, pixel_size));
570 TEST_P(ResourceProviderTest, TransferGLResources) {
571 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
572 return;
573 gfx::Size size(1, 1);
574 ResourceFormat format = RGBA_8888;
575 size_t pixel_size = TextureSizeBytes(size, format);
576 ASSERT_EQ(4U, pixel_size);
578 ResourceId id1 = child_resource_provider_->CreateResource(
579 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
580 uint8_t data1[4] = { 1, 2, 3, 4 };
581 child_resource_provider_->CopyToResource(id1, data1, size);
583 ResourceId id2 = child_resource_provider_->CreateResource(
584 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
585 uint8_t data2[4] = { 5, 5, 5, 5 };
586 child_resource_provider_->CopyToResource(id2, data2, size);
588 ResourceId id3 = child_resource_provider_->CreateResource(
589 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
591 ResourceProvider::ScopedWriteLockGpuMemoryBuffer lock(
592 child_resource_provider_.get(), id3);
593 EXPECT_TRUE(lock.GetGpuMemoryBuffer());
596 GLuint external_texture_id = child_context_->createExternalTexture();
598 gpu::Mailbox external_mailbox;
599 child_context_->genMailboxCHROMIUM(external_mailbox.name);
600 child_context_->produceTextureDirectCHROMIUM(
601 external_texture_id, GL_TEXTURE_EXTERNAL_OES, external_mailbox.name);
602 const GLuint external_sync_point = child_context_->insertSyncPoint();
603 ResourceId id4 = child_resource_provider_->CreateResourceFromTextureMailbox(
604 TextureMailbox(external_mailbox, GL_TEXTURE_EXTERNAL_OES,
605 external_sync_point),
606 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback)));
608 ReturnedResourceArray returned_to_child;
609 int child_id =
610 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
612 // Transfer some resources to the parent.
613 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
614 resource_ids_to_transfer.push_back(id1);
615 resource_ids_to_transfer.push_back(id2);
616 resource_ids_to_transfer.push_back(id3);
617 resource_ids_to_transfer.push_back(id4);
618 TransferableResourceArray list;
619 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
620 &list);
621 ASSERT_EQ(4u, list.size());
622 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
623 EXPECT_NE(0u, list[1].mailbox_holder.sync_point);
624 EXPECT_EQ(list[0].mailbox_holder.sync_point,
625 list[1].mailbox_holder.sync_point);
626 EXPECT_NE(0u, list[2].mailbox_holder.sync_point);
627 EXPECT_EQ(list[0].mailbox_holder.sync_point,
628 list[2].mailbox_holder.sync_point);
629 EXPECT_EQ(external_sync_point, list[3].mailbox_holder.sync_point);
630 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
631 list[0].mailbox_holder.texture_target);
632 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
633 list[1].mailbox_holder.texture_target);
634 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
635 list[2].mailbox_holder.texture_target);
636 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_EXTERNAL_OES),
637 list[3].mailbox_holder.texture_target);
638 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
639 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
640 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
641 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id4));
642 resource_provider_->ReceiveFromChild(child_id, list);
643 EXPECT_NE(list[0].mailbox_holder.sync_point,
644 context3d_->last_waited_sync_point());
646 resource_provider_->WaitSyncPointIfNeeded(list[0].id);
647 ResourceProvider::ScopedReadLockGL lock(resource_provider_.get(),
648 list[0].id);
650 EXPECT_EQ(list[0].mailbox_holder.sync_point,
651 context3d_->last_waited_sync_point());
652 ResourceProvider::ResourceIdSet resource_ids_to_receive;
653 resource_ids_to_receive.insert(id1);
654 resource_ids_to_receive.insert(id2);
655 resource_ids_to_receive.insert(id3);
656 resource_ids_to_receive.insert(id4);
657 resource_provider_->DeclareUsedResourcesFromChild(child_id,
658 resource_ids_to_receive);
661 EXPECT_EQ(4u, resource_provider_->num_resources());
662 ResourceProvider::ResourceIdMap resource_map =
663 resource_provider_->GetChildToParentMap(child_id);
664 ResourceId mapped_id1 = resource_map[id1];
665 ResourceId mapped_id2 = resource_map[id2];
666 ResourceId mapped_id3 = resource_map[id3];
667 ResourceId mapped_id4 = resource_map[id4];
668 EXPECT_NE(0u, mapped_id1);
669 EXPECT_NE(0u, mapped_id2);
670 EXPECT_NE(0u, mapped_id3);
671 EXPECT_NE(0u, mapped_id4);
672 EXPECT_FALSE(resource_provider_->InUseByConsumer(id1));
673 EXPECT_FALSE(resource_provider_->InUseByConsumer(id2));
674 EXPECT_FALSE(resource_provider_->InUseByConsumer(id3));
675 EXPECT_FALSE(resource_provider_->InUseByConsumer(id4));
677 uint8_t result[4] = { 0 };
678 GetResourcePixels(
679 resource_provider_.get(), context(), mapped_id1, size, format, result);
680 EXPECT_EQ(0, memcmp(data1, result, pixel_size));
682 GetResourcePixels(
683 resource_provider_.get(), context(), mapped_id2, size, format, result);
684 EXPECT_EQ(0, memcmp(data2, result, pixel_size));
687 // Check that transfering again the same resource from the child to the
688 // parent works.
689 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
690 resource_ids_to_transfer.push_back(id1);
691 resource_ids_to_transfer.push_back(id2);
692 resource_ids_to_transfer.push_back(id3);
693 TransferableResourceArray list;
694 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
695 &list);
696 EXPECT_EQ(3u, list.size());
697 EXPECT_EQ(id1, list[0].id);
698 EXPECT_EQ(id2, list[1].id);
699 EXPECT_EQ(id3, list[2].id);
700 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
701 list[0].mailbox_holder.texture_target);
702 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
703 list[1].mailbox_holder.texture_target);
704 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
705 list[2].mailbox_holder.texture_target);
706 ReturnedResourceArray returned;
707 TransferableResource::ReturnResources(list, &returned);
708 child_resource_provider_->ReceiveReturnsFromParent(returned);
709 // ids were exported twice, we returned them only once, they should still
710 // be in-use.
711 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
712 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
713 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
716 EXPECT_EQ(0u, returned_to_child.size());
718 // Transfer resources back from the parent to the child. Set no resources as
719 // being in use.
720 ResourceProvider::ResourceIdSet no_resources;
721 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
723 ASSERT_EQ(4u, returned_to_child.size());
724 EXPECT_NE(0u, returned_to_child[0].sync_point);
725 EXPECT_NE(0u, returned_to_child[1].sync_point);
726 EXPECT_NE(0u, returned_to_child[2].sync_point);
727 EXPECT_NE(0u, returned_to_child[3].sync_point);
728 EXPECT_FALSE(returned_to_child[0].lost);
729 EXPECT_FALSE(returned_to_child[1].lost);
730 EXPECT_FALSE(returned_to_child[2].lost);
731 EXPECT_FALSE(returned_to_child[3].lost);
732 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
733 returned_to_child.clear();
735 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id1));
736 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id2));
737 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id3));
738 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id4));
741 child_resource_provider_->WaitSyncPointIfNeeded(id1);
742 ResourceProvider::ScopedReadLockGL lock(child_resource_provider_.get(),
743 id1);
744 ASSERT_NE(0U, lock.texture_id());
745 child_context_->bindTexture(GL_TEXTURE_2D, lock.texture_id());
746 child_context_->GetPixels(size, format, result);
747 EXPECT_EQ(0, memcmp(data1, result, pixel_size));
750 child_resource_provider_->WaitSyncPointIfNeeded(id2);
751 ResourceProvider::ScopedReadLockGL lock(child_resource_provider_.get(),
752 id2);
753 ASSERT_NE(0U, lock.texture_id());
754 child_context_->bindTexture(GL_TEXTURE_2D, lock.texture_id());
755 child_context_->GetPixels(size, format, result);
756 EXPECT_EQ(0, memcmp(data2, result, pixel_size));
759 child_resource_provider_->WaitSyncPointIfNeeded(id3);
760 ResourceProvider::ScopedReadLockGL lock(child_resource_provider_.get(),
761 id3);
762 ASSERT_NE(0U, lock.texture_id());
763 child_context_->bindTexture(GL_TEXTURE_2D, lock.texture_id());
766 // Transfer resources to the parent again.
767 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
768 resource_ids_to_transfer.push_back(id1);
769 resource_ids_to_transfer.push_back(id2);
770 resource_ids_to_transfer.push_back(id3);
771 resource_ids_to_transfer.push_back(id4);
772 TransferableResourceArray list;
773 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
774 &list);
775 ASSERT_EQ(4u, list.size());
776 EXPECT_EQ(id1, list[0].id);
777 EXPECT_EQ(id2, list[1].id);
778 EXPECT_EQ(id3, list[2].id);
779 EXPECT_EQ(id4, list[3].id);
780 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
781 EXPECT_NE(0u, list[1].mailbox_holder.sync_point);
782 EXPECT_NE(0u, list[2].mailbox_holder.sync_point);
783 EXPECT_NE(0u, list[3].mailbox_holder.sync_point);
784 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
785 list[0].mailbox_holder.texture_target);
786 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
787 list[1].mailbox_holder.texture_target);
788 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
789 list[2].mailbox_holder.texture_target);
790 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_EXTERNAL_OES),
791 list[3].mailbox_holder.texture_target);
792 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
793 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
794 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
795 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id4));
796 resource_provider_->ReceiveFromChild(child_id, list);
797 ResourceProvider::ResourceIdSet resource_ids_to_receive;
798 resource_ids_to_receive.insert(id1);
799 resource_ids_to_receive.insert(id2);
800 resource_ids_to_receive.insert(id3);
801 resource_ids_to_receive.insert(id4);
802 resource_provider_->DeclareUsedResourcesFromChild(child_id,
803 resource_ids_to_receive);
806 EXPECT_EQ(0u, returned_to_child.size());
808 EXPECT_EQ(4u, resource_provider_->num_resources());
809 resource_provider_->DestroyChild(child_id);
810 EXPECT_EQ(0u, resource_provider_->num_resources());
812 ASSERT_EQ(4u, returned_to_child.size());
813 EXPECT_NE(0u, returned_to_child[0].sync_point);
814 EXPECT_NE(0u, returned_to_child[1].sync_point);
815 EXPECT_NE(0u, returned_to_child[2].sync_point);
816 EXPECT_NE(0u, returned_to_child[3].sync_point);
817 EXPECT_FALSE(returned_to_child[0].lost);
818 EXPECT_FALSE(returned_to_child[1].lost);
819 EXPECT_FALSE(returned_to_child[2].lost);
820 EXPECT_FALSE(returned_to_child[3].lost);
823 class ResourceProviderTestNoSyncPoint : public ResourceProviderTest {
824 public:
825 ResourceProviderTestNoSyncPoint() : ResourceProviderTest(false) {
826 EXPECT_EQ(ResourceProvider::RESOURCE_TYPE_GL_TEXTURE, GetParam());
830 TEST_P(ResourceProviderTestNoSyncPoint, TransferGLResources) {
831 gfx::Size size(1, 1);
832 ResourceFormat format = RGBA_8888;
833 size_t pixel_size = TextureSizeBytes(size, format);
834 ASSERT_EQ(4U, pixel_size);
836 ResourceId id1 = child_resource_provider_->CreateResource(
837 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
838 uint8_t data1[4] = {1, 2, 3, 4};
839 child_resource_provider_->CopyToResource(id1, data1, size);
841 ResourceId id2 = child_resource_provider_->CreateResource(
842 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
844 // Ensure locking the memory buffer doesn't create an unnecessary sync
845 // point.
846 ResourceProvider::ScopedWriteLockGpuMemoryBuffer lock(
847 child_resource_provider_.get(), id2);
848 EXPECT_TRUE(lock.GetGpuMemoryBuffer());
851 GLuint external_texture_id = child_context_->createExternalTexture();
853 // A sync point is specified directly and should be used.
854 gpu::Mailbox external_mailbox;
855 child_context_->genMailboxCHROMIUM(external_mailbox.name);
856 child_context_->produceTextureDirectCHROMIUM(
857 external_texture_id, GL_TEXTURE_EXTERNAL_OES, external_mailbox.name);
858 const GLuint external_sync_point = child_context_->insertSyncPoint();
859 ResourceId id3 = child_resource_provider_->CreateResourceFromTextureMailbox(
860 TextureMailbox(external_mailbox, GL_TEXTURE_EXTERNAL_OES,
861 external_sync_point),
862 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback)));
864 ReturnedResourceArray returned_to_child;
865 int child_id =
866 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
867 resource_provider_->SetChildNeedsSyncPoints(child_id, false);
869 // Transfer some resources to the parent.
870 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
871 resource_ids_to_transfer.push_back(id1);
872 resource_ids_to_transfer.push_back(id2);
873 resource_ids_to_transfer.push_back(id3);
874 TransferableResourceArray list;
875 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
876 &list);
877 ASSERT_EQ(3u, list.size());
878 // Standard resources shouldn't require creating and sending a sync point.
879 EXPECT_EQ(0u, list[0].mailbox_holder.sync_point);
880 EXPECT_EQ(0u, list[1].mailbox_holder.sync_point);
881 // A given sync point should be passed through.
882 EXPECT_EQ(external_sync_point, list[2].mailbox_holder.sync_point);
883 resource_provider_->ReceiveFromChild(child_id, list);
885 ResourceProvider::ResourceIdSet resource_ids_to_receive;
886 resource_ids_to_receive.insert(id1);
887 resource_ids_to_receive.insert(id2);
888 resource_ids_to_receive.insert(id3);
889 resource_provider_->DeclareUsedResourcesFromChild(child_id,
890 resource_ids_to_receive);
894 EXPECT_EQ(0u, returned_to_child.size());
896 // Transfer resources back from the parent to the child. Set no resources as
897 // being in use.
898 ResourceProvider::ResourceIdSet no_resources;
899 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
901 ASSERT_EQ(3u, returned_to_child.size());
902 std::map<ResourceId, unsigned int> returned_sync_points;
903 for (const auto& returned : returned_to_child)
904 returned_sync_points[returned.id] = returned.sync_point;
906 EXPECT_TRUE(returned_sync_points.find(id1) != returned_sync_points.end());
907 // No new sync point should be created transferring back.
908 EXPECT_TRUE(returned_sync_points.find(id1) != returned_sync_points.end());
909 EXPECT_EQ(0u, returned_sync_points[id1]);
910 EXPECT_TRUE(returned_sync_points.find(id2) != returned_sync_points.end());
911 EXPECT_EQ(0u, returned_sync_points[id2]);
912 // Original sync point given should be returned.
913 EXPECT_TRUE(returned_sync_points.find(id3) != returned_sync_points.end());
914 EXPECT_EQ(external_sync_point, returned_sync_points[id3]);
915 EXPECT_FALSE(returned_to_child[0].lost);
916 EXPECT_FALSE(returned_to_child[1].lost);
917 EXPECT_FALSE(returned_to_child[2].lost);
918 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
919 returned_to_child.clear();
922 resource_provider_->DestroyChild(child_id);
925 INSTANTIATE_TEST_CASE_P(
926 ResourceProviderTests,
927 ResourceProviderTestNoSyncPoint,
928 ::testing::Values(ResourceProvider::RESOURCE_TYPE_GL_TEXTURE));
930 TEST_P(ResourceProviderTest, ReadLockCountStopsReturnToChildOrDelete) {
931 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
932 return;
933 gfx::Size size(1, 1);
934 ResourceFormat format = RGBA_8888;
936 ResourceId id1 = child_resource_provider_->CreateResource(
937 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
938 uint8_t data1[4] = {1, 2, 3, 4};
939 child_resource_provider_->CopyToResource(id1, data1, size);
941 ReturnedResourceArray returned_to_child;
942 int child_id =
943 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
945 // Transfer some resources to the parent.
946 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
947 resource_ids_to_transfer.push_back(id1);
948 TransferableResourceArray list;
949 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
950 &list);
951 ASSERT_EQ(1u, list.size());
952 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
954 resource_provider_->ReceiveFromChild(child_id, list);
956 resource_provider_->WaitSyncPointIfNeeded(list[0].id);
957 ResourceProvider::ScopedReadLockGL lock(resource_provider_.get(),
958 list[0].id);
960 resource_provider_->DeclareUsedResourcesFromChild(
961 child_id, ResourceProvider::ResourceIdSet());
962 EXPECT_EQ(0u, returned_to_child.size());
965 EXPECT_EQ(1u, returned_to_child.size());
966 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
969 child_resource_provider_->WaitSyncPointIfNeeded(id1);
970 ResourceProvider::ScopedReadLockGL lock(child_resource_provider_.get(),
971 id1);
972 child_resource_provider_->DeleteResource(id1);
973 EXPECT_EQ(1u, child_resource_provider_->num_resources());
974 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
977 EXPECT_EQ(0u, child_resource_provider_->num_resources());
978 resource_provider_->DestroyChild(child_id);
981 class TestFence : public ResourceProvider::Fence {
982 public:
983 TestFence() {}
985 void Set() override {}
986 bool HasPassed() override { return passed; }
987 void Wait() override {}
989 bool passed = false;
991 private:
992 ~TestFence() override {}
995 TEST_P(ResourceProviderTest, ReadLockFenceStopsReturnToChildOrDelete) {
996 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
997 return;
998 gfx::Size size(1, 1);
999 ResourceFormat format = RGBA_8888;
1001 ResourceId id1 = child_resource_provider_->CreateResource(
1002 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
1003 uint8_t data1[4] = {1, 2, 3, 4};
1004 child_resource_provider_->CopyToResource(id1, data1, size);
1005 child_resource_provider_->EnableReadLockFencesForTesting(id1);
1006 ReturnedResourceArray returned_to_child;
1007 int child_id =
1008 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1010 // Transfer some resources to the parent.
1011 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1012 resource_ids_to_transfer.push_back(id1);
1013 TransferableResourceArray list;
1014 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1015 &list);
1016 ASSERT_EQ(1u, list.size());
1017 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1018 EXPECT_TRUE(list[0].read_lock_fences_enabled);
1020 resource_provider_->ReceiveFromChild(child_id, list);
1022 scoped_refptr<TestFence> fence(new TestFence);
1023 resource_provider_->SetReadLockFence(fence.get());
1025 unsigned parent_id = list.front().id;
1026 resource_provider_->WaitSyncPointIfNeeded(parent_id);
1027 ResourceProvider::ScopedReadLockGL lock(resource_provider_.get(),
1028 parent_id);
1030 resource_provider_->DeclareUsedResourcesFromChild(
1031 child_id, ResourceProvider::ResourceIdSet());
1032 EXPECT_EQ(0u, returned_to_child.size());
1034 resource_provider_->DeclareUsedResourcesFromChild(
1035 child_id, ResourceProvider::ResourceIdSet());
1036 EXPECT_EQ(0u, returned_to_child.size());
1037 fence->passed = true;
1039 resource_provider_->DeclareUsedResourcesFromChild(
1040 child_id, ResourceProvider::ResourceIdSet());
1041 EXPECT_EQ(1u, returned_to_child.size());
1043 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
1044 child_resource_provider_->DeleteResource(id1);
1045 EXPECT_EQ(0u, child_resource_provider_->num_resources());
1048 TEST_P(ResourceProviderTest, ReadLockFenceDestroyChild) {
1049 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
1050 return;
1051 gfx::Size size(1, 1);
1052 ResourceFormat format = RGBA_8888;
1054 ResourceId id1 = child_resource_provider_->CreateResource(
1055 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
1056 uint8_t data[4] = {1, 2, 3, 4};
1057 child_resource_provider_->CopyToResource(id1, data, size);
1058 child_resource_provider_->EnableReadLockFencesForTesting(id1);
1060 ResourceId id2 = child_resource_provider_->CreateResource(
1061 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
1062 child_resource_provider_->CopyToResource(id2, data, size);
1064 ReturnedResourceArray returned_to_child;
1065 int child_id =
1066 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1068 // Transfer resources to the parent.
1069 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1070 resource_ids_to_transfer.push_back(id1);
1071 resource_ids_to_transfer.push_back(id2);
1072 TransferableResourceArray list;
1073 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1074 &list);
1075 ASSERT_EQ(2u, list.size());
1076 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1077 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
1079 resource_provider_->ReceiveFromChild(child_id, list);
1081 scoped_refptr<TestFence> fence(new TestFence);
1082 resource_provider_->SetReadLockFence(fence.get());
1084 for (size_t i = 0; i < list.size(); i++) {
1085 unsigned parent_id = list[i].id;
1086 resource_provider_->WaitSyncPointIfNeeded(parent_id);
1087 ResourceProvider::ScopedReadLockGL lock(resource_provider_.get(),
1088 parent_id);
1091 EXPECT_EQ(0u, returned_to_child.size());
1093 EXPECT_EQ(2u, resource_provider_->num_resources());
1095 resource_provider_->DestroyChild(child_id);
1097 EXPECT_EQ(0u, resource_provider_->num_resources());
1098 EXPECT_EQ(2u, returned_to_child.size());
1100 // id1 should be lost and id2 should not.
1101 EXPECT_EQ(returned_to_child[0].lost, returned_to_child[0].id == id1);
1102 EXPECT_EQ(returned_to_child[1].lost, returned_to_child[1].id == id1);
1104 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
1105 child_resource_provider_->DeleteResource(id1);
1106 child_resource_provider_->DeleteResource(id2);
1107 EXPECT_EQ(0u, child_resource_provider_->num_resources());
1110 TEST_P(ResourceProviderTest, ReadLockFenceContextLost) {
1111 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
1112 return;
1113 gfx::Size size(1, 1);
1114 ResourceFormat format = RGBA_8888;
1116 ResourceId id1 = child_resource_provider_->CreateResource(
1117 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
1118 uint8_t data[4] = {1, 2, 3, 4};
1119 child_resource_provider_->CopyToResource(id1, data, size);
1120 child_resource_provider_->EnableReadLockFencesForTesting(id1);
1122 ResourceId id2 = child_resource_provider_->CreateResource(
1123 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
1124 child_resource_provider_->CopyToResource(id2, data, size);
1126 ReturnedResourceArray returned_to_child;
1127 int child_id =
1128 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1130 // Transfer resources to the parent.
1131 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1132 resource_ids_to_transfer.push_back(id1);
1133 resource_ids_to_transfer.push_back(id2);
1134 TransferableResourceArray list;
1135 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1136 &list);
1137 ASSERT_EQ(2u, list.size());
1138 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1139 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
1141 resource_provider_->ReceiveFromChild(child_id, list);
1143 scoped_refptr<TestFence> fence(new TestFence);
1144 resource_provider_->SetReadLockFence(fence.get());
1146 for (size_t i = 0; i < list.size(); i++) {
1147 unsigned parent_id = list[i].id;
1148 resource_provider_->WaitSyncPointIfNeeded(parent_id);
1149 ResourceProvider::ScopedReadLockGL lock(resource_provider_.get(),
1150 parent_id);
1153 EXPECT_EQ(0u, returned_to_child.size());
1155 EXPECT_EQ(2u, resource_provider_->num_resources());
1156 resource_provider_->DidLoseOutputSurface();
1157 resource_provider_ = nullptr;
1159 EXPECT_EQ(2u, returned_to_child.size());
1161 EXPECT_TRUE(returned_to_child[0].lost);
1162 EXPECT_TRUE(returned_to_child[1].lost);
1165 TEST_P(ResourceProviderTest, TransferSoftwareResources) {
1166 if (GetParam() != ResourceProvider::RESOURCE_TYPE_BITMAP)
1167 return;
1169 gfx::Size size(1, 1);
1170 ResourceFormat format = RGBA_8888;
1171 size_t pixel_size = TextureSizeBytes(size, format);
1172 ASSERT_EQ(4U, pixel_size);
1174 ResourceId id1 = child_resource_provider_->CreateResource(
1175 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
1176 uint8_t data1[4] = { 1, 2, 3, 4 };
1177 child_resource_provider_->CopyToResource(id1, data1, size);
1179 ResourceId id2 = child_resource_provider_->CreateResource(
1180 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
1181 uint8_t data2[4] = { 5, 5, 5, 5 };
1182 child_resource_provider_->CopyToResource(id2, data2, size);
1184 scoped_ptr<SharedBitmap> shared_bitmap(CreateAndFillSharedBitmap(
1185 shared_bitmap_manager_.get(), gfx::Size(1, 1), 0));
1186 SharedBitmap* shared_bitmap_ptr = shared_bitmap.get();
1187 ResourceId id3 = child_resource_provider_->CreateResourceFromTextureMailbox(
1188 TextureMailbox(shared_bitmap_ptr, gfx::Size(1, 1)),
1189 SingleReleaseCallbackImpl::Create(base::Bind(
1190 &SharedBitmapReleaseCallback, base::Passed(&shared_bitmap))));
1192 ReturnedResourceArray returned_to_child;
1193 int child_id =
1194 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1196 // Transfer some resources to the parent.
1197 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1198 resource_ids_to_transfer.push_back(id1);
1199 resource_ids_to_transfer.push_back(id2);
1200 resource_ids_to_transfer.push_back(id3);
1201 TransferableResourceArray list;
1202 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1203 &list);
1204 ASSERT_EQ(3u, list.size());
1205 EXPECT_EQ(0u, list[0].mailbox_holder.sync_point);
1206 EXPECT_EQ(0u, list[1].mailbox_holder.sync_point);
1207 EXPECT_EQ(0u, list[2].mailbox_holder.sync_point);
1208 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1209 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
1210 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
1211 resource_provider_->ReceiveFromChild(child_id, list);
1212 ResourceProvider::ResourceIdSet resource_ids_to_receive;
1213 resource_ids_to_receive.insert(id1);
1214 resource_ids_to_receive.insert(id2);
1215 resource_ids_to_receive.insert(id3);
1216 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1217 resource_ids_to_receive);
1220 EXPECT_EQ(3u, resource_provider_->num_resources());
1221 ResourceProvider::ResourceIdMap resource_map =
1222 resource_provider_->GetChildToParentMap(child_id);
1223 ResourceId mapped_id1 = resource_map[id1];
1224 ResourceId mapped_id2 = resource_map[id2];
1225 ResourceId mapped_id3 = resource_map[id3];
1226 EXPECT_NE(0u, mapped_id1);
1227 EXPECT_NE(0u, mapped_id2);
1228 EXPECT_NE(0u, mapped_id3);
1229 EXPECT_FALSE(resource_provider_->InUseByConsumer(id1));
1230 EXPECT_FALSE(resource_provider_->InUseByConsumer(id2));
1231 EXPECT_FALSE(resource_provider_->InUseByConsumer(id3));
1233 uint8_t result[4] = { 0 };
1234 GetResourcePixels(
1235 resource_provider_.get(), context(), mapped_id1, size, format, result);
1236 EXPECT_EQ(0, memcmp(data1, result, pixel_size));
1238 GetResourcePixels(
1239 resource_provider_.get(), context(), mapped_id2, size, format, result);
1240 EXPECT_EQ(0, memcmp(data2, result, pixel_size));
1243 // Check that transfering again the same resource from the child to the
1244 // parent works.
1245 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1246 resource_ids_to_transfer.push_back(id1);
1247 resource_ids_to_transfer.push_back(id2);
1248 TransferableResourceArray list;
1249 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1250 &list);
1251 EXPECT_EQ(2u, list.size());
1252 EXPECT_EQ(id1, list[0].id);
1253 EXPECT_EQ(id2, list[1].id);
1254 ReturnedResourceArray returned;
1255 TransferableResource::ReturnResources(list, &returned);
1256 child_resource_provider_->ReceiveReturnsFromParent(returned);
1257 // ids were exported twice, we returned them only once, they should still
1258 // be in-use.
1259 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1260 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
1263 EXPECT_EQ(0u, returned_to_child.size());
1265 // Transfer resources back from the parent to the child. Set no resources as
1266 // being in use.
1267 ResourceProvider::ResourceIdSet no_resources;
1268 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
1270 ASSERT_EQ(3u, returned_to_child.size());
1271 EXPECT_EQ(0u, returned_to_child[0].sync_point);
1272 EXPECT_EQ(0u, returned_to_child[1].sync_point);
1273 EXPECT_EQ(0u, returned_to_child[2].sync_point);
1274 std::set<ResourceId> expected_ids;
1275 expected_ids.insert(id1);
1276 expected_ids.insert(id2);
1277 expected_ids.insert(id3);
1278 std::set<ResourceId> returned_ids;
1279 for (unsigned i = 0; i < 3; i++)
1280 returned_ids.insert(returned_to_child[i].id);
1281 EXPECT_EQ(expected_ids, returned_ids);
1282 EXPECT_FALSE(returned_to_child[0].lost);
1283 EXPECT_FALSE(returned_to_child[1].lost);
1284 EXPECT_FALSE(returned_to_child[2].lost);
1285 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
1286 returned_to_child.clear();
1288 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id1));
1289 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id2));
1290 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id3));
1293 ResourceProvider::ScopedReadLockSoftware lock(
1294 child_resource_provider_.get(), id1);
1295 const SkBitmap* sk_bitmap = lock.sk_bitmap();
1296 EXPECT_EQ(sk_bitmap->width(), size.width());
1297 EXPECT_EQ(sk_bitmap->height(), size.height());
1298 EXPECT_EQ(0, memcmp(data1, sk_bitmap->getPixels(), pixel_size));
1301 ResourceProvider::ScopedReadLockSoftware lock(
1302 child_resource_provider_.get(), id2);
1303 const SkBitmap* sk_bitmap = lock.sk_bitmap();
1304 EXPECT_EQ(sk_bitmap->width(), size.width());
1305 EXPECT_EQ(sk_bitmap->height(), size.height());
1306 EXPECT_EQ(0, memcmp(data2, sk_bitmap->getPixels(), pixel_size));
1309 // Transfer resources to the parent again.
1310 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1311 resource_ids_to_transfer.push_back(id1);
1312 resource_ids_to_transfer.push_back(id2);
1313 resource_ids_to_transfer.push_back(id3);
1314 TransferableResourceArray list;
1315 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1316 &list);
1317 ASSERT_EQ(3u, list.size());
1318 EXPECT_EQ(id1, list[0].id);
1319 EXPECT_EQ(id2, list[1].id);
1320 EXPECT_EQ(id3, list[2].id);
1321 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1322 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
1323 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
1324 resource_provider_->ReceiveFromChild(child_id, list);
1325 ResourceProvider::ResourceIdSet resource_ids_to_receive;
1326 resource_ids_to_receive.insert(id1);
1327 resource_ids_to_receive.insert(id2);
1328 resource_ids_to_receive.insert(id3);
1329 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1330 resource_ids_to_receive);
1333 EXPECT_EQ(0u, returned_to_child.size());
1335 EXPECT_EQ(3u, resource_provider_->num_resources());
1336 resource_provider_->DestroyChild(child_id);
1337 EXPECT_EQ(0u, resource_provider_->num_resources());
1339 ASSERT_EQ(3u, returned_to_child.size());
1340 EXPECT_EQ(0u, returned_to_child[0].sync_point);
1341 EXPECT_EQ(0u, returned_to_child[1].sync_point);
1342 EXPECT_EQ(0u, returned_to_child[2].sync_point);
1343 std::set<ResourceId> expected_ids;
1344 expected_ids.insert(id1);
1345 expected_ids.insert(id2);
1346 expected_ids.insert(id3);
1347 std::set<ResourceId> returned_ids;
1348 for (unsigned i = 0; i < 3; i++)
1349 returned_ids.insert(returned_to_child[i].id);
1350 EXPECT_EQ(expected_ids, returned_ids);
1351 EXPECT_FALSE(returned_to_child[0].lost);
1352 EXPECT_FALSE(returned_to_child[1].lost);
1353 EXPECT_FALSE(returned_to_child[2].lost);
1356 TEST_P(ResourceProviderTest, TransferGLToSoftware) {
1357 if (GetParam() != ResourceProvider::RESOURCE_TYPE_BITMAP)
1358 return;
1360 scoped_ptr<ResourceProviderContext> child_context_owned(
1361 ResourceProviderContext::Create(shared_data_.get()));
1363 FakeOutputSurfaceClient child_output_surface_client;
1364 scoped_ptr<OutputSurface> child_output_surface(
1365 FakeOutputSurface::Create3d(child_context_owned.Pass()));
1366 CHECK(child_output_surface->BindToClient(&child_output_surface_client));
1368 scoped_ptr<ResourceProvider> child_resource_provider(ResourceProvider::Create(
1369 child_output_surface.get(), shared_bitmap_manager_.get(),
1370 gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false));
1372 gfx::Size size(1, 1);
1373 ResourceFormat format = RGBA_8888;
1374 size_t pixel_size = TextureSizeBytes(size, format);
1375 ASSERT_EQ(4U, pixel_size);
1377 ResourceId id1 = child_resource_provider->CreateResource(
1378 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
1379 uint8_t data1[4] = { 1, 2, 3, 4 };
1380 child_resource_provider->CopyToResource(id1, data1, size);
1382 ReturnedResourceArray returned_to_child;
1383 int child_id =
1384 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1386 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1387 resource_ids_to_transfer.push_back(id1);
1388 TransferableResourceArray list;
1389 child_resource_provider->PrepareSendToParent(resource_ids_to_transfer,
1390 &list);
1391 ASSERT_EQ(1u, list.size());
1392 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
1393 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
1394 list[0].mailbox_holder.texture_target);
1395 EXPECT_TRUE(child_resource_provider->InUseByConsumer(id1));
1396 resource_provider_->ReceiveFromChild(child_id, list);
1399 EXPECT_EQ(0u, resource_provider_->num_resources());
1400 ASSERT_EQ(1u, returned_to_child.size());
1401 EXPECT_EQ(returned_to_child[0].id, id1);
1402 ResourceProvider::ResourceIdMap resource_map =
1403 resource_provider_->GetChildToParentMap(child_id);
1404 ResourceId mapped_id1 = resource_map[id1];
1405 EXPECT_EQ(0u, mapped_id1);
1407 resource_provider_->DestroyChild(child_id);
1408 EXPECT_EQ(0u, resource_provider_->num_resources());
1410 ASSERT_EQ(1u, returned_to_child.size());
1411 EXPECT_FALSE(returned_to_child[0].lost);
1414 TEST_P(ResourceProviderTest, TransferInvalidSoftware) {
1415 if (GetParam() != ResourceProvider::RESOURCE_TYPE_BITMAP)
1416 return;
1418 gfx::Size size(1, 1);
1419 ResourceFormat format = RGBA_8888;
1420 size_t pixel_size = TextureSizeBytes(size, format);
1421 ASSERT_EQ(4U, pixel_size);
1423 ResourceId id1 = child_resource_provider_->CreateResource(
1424 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
1425 uint8_t data1[4] = { 1, 2, 3, 4 };
1426 child_resource_provider_->CopyToResource(id1, data1, size);
1428 ReturnedResourceArray returned_to_child;
1429 int child_id =
1430 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1432 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1433 resource_ids_to_transfer.push_back(id1);
1434 TransferableResourceArray list;
1435 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1436 &list);
1437 ASSERT_EQ(1u, list.size());
1438 // Make invalid.
1439 list[0].mailbox_holder.mailbox.name[1] = 5;
1440 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1441 resource_provider_->ReceiveFromChild(child_id, list);
1444 EXPECT_EQ(1u, resource_provider_->num_resources());
1445 EXPECT_EQ(0u, returned_to_child.size());
1447 ResourceProvider::ResourceIdMap resource_map =
1448 resource_provider_->GetChildToParentMap(child_id);
1449 ResourceId mapped_id1 = resource_map[id1];
1450 EXPECT_NE(0u, mapped_id1);
1452 ResourceProvider::ScopedReadLockSoftware lock(resource_provider_.get(),
1453 mapped_id1);
1454 EXPECT_FALSE(lock.valid());
1457 resource_provider_->DestroyChild(child_id);
1458 EXPECT_EQ(0u, resource_provider_->num_resources());
1460 ASSERT_EQ(1u, returned_to_child.size());
1461 EXPECT_FALSE(returned_to_child[0].lost);
1464 TEST_P(ResourceProviderTest, DeleteExportedResources) {
1465 gfx::Size size(1, 1);
1466 ResourceFormat format = RGBA_8888;
1467 size_t pixel_size = TextureSizeBytes(size, format);
1468 ASSERT_EQ(4U, pixel_size);
1470 ResourceId id1 = child_resource_provider_->CreateResource(
1471 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
1472 uint8_t data1[4] = { 1, 2, 3, 4 };
1473 child_resource_provider_->CopyToResource(id1, data1, size);
1475 ResourceId id2 = child_resource_provider_->CreateResource(
1476 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
1477 uint8_t data2[4] = {5, 5, 5, 5};
1478 child_resource_provider_->CopyToResource(id2, data2, size);
1480 ReturnedResourceArray returned_to_child;
1481 int child_id =
1482 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1484 // Transfer some resources to the parent.
1485 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1486 resource_ids_to_transfer.push_back(id1);
1487 resource_ids_to_transfer.push_back(id2);
1488 TransferableResourceArray list;
1489 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1490 &list);
1491 ASSERT_EQ(2u, list.size());
1492 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) {
1493 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
1494 EXPECT_NE(0u, list[1].mailbox_holder.sync_point);
1496 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1497 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
1498 resource_provider_->ReceiveFromChild(child_id, list);
1499 ResourceProvider::ResourceIdSet resource_ids_to_receive;
1500 resource_ids_to_receive.insert(id1);
1501 resource_ids_to_receive.insert(id2);
1502 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1503 resource_ids_to_receive);
1506 EXPECT_EQ(2u, resource_provider_->num_resources());
1507 ResourceProvider::ResourceIdMap resource_map =
1508 resource_provider_->GetChildToParentMap(child_id);
1509 ResourceId mapped_id1 = resource_map[id1];
1510 ResourceId mapped_id2 = resource_map[id2];
1511 EXPECT_NE(0u, mapped_id1);
1512 EXPECT_NE(0u, mapped_id2);
1513 EXPECT_FALSE(resource_provider_->InUseByConsumer(id1));
1514 EXPECT_FALSE(resource_provider_->InUseByConsumer(id2));
1517 // The parent transfers the resources to the grandparent.
1518 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1519 resource_ids_to_transfer.push_back(mapped_id1);
1520 resource_ids_to_transfer.push_back(mapped_id2);
1521 TransferableResourceArray list;
1522 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
1524 ASSERT_EQ(2u, list.size());
1525 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) {
1526 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
1527 EXPECT_NE(0u, list[1].mailbox_holder.sync_point);
1529 EXPECT_TRUE(resource_provider_->InUseByConsumer(id1));
1530 EXPECT_TRUE(resource_provider_->InUseByConsumer(id2));
1532 // Release the resource in the parent. Set no resources as being in use. The
1533 // resources are exported so that can't be transferred back yet.
1534 ResourceProvider::ResourceIdSet no_resources;
1535 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
1537 EXPECT_EQ(0u, returned_to_child.size());
1538 EXPECT_EQ(2u, resource_provider_->num_resources());
1540 // Return the resources from the grandparent to the parent. They should be
1541 // returned to the child then.
1542 EXPECT_EQ(2u, list.size());
1543 EXPECT_EQ(mapped_id1, list[0].id);
1544 EXPECT_EQ(mapped_id2, list[1].id);
1545 ReturnedResourceArray returned;
1546 TransferableResource::ReturnResources(list, &returned);
1547 resource_provider_->ReceiveReturnsFromParent(returned);
1549 EXPECT_EQ(0u, resource_provider_->num_resources());
1550 ASSERT_EQ(2u, returned_to_child.size());
1551 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) {
1552 EXPECT_NE(0u, returned_to_child[0].sync_point);
1553 EXPECT_NE(0u, returned_to_child[1].sync_point);
1555 EXPECT_FALSE(returned_to_child[0].lost);
1556 EXPECT_FALSE(returned_to_child[1].lost);
1560 TEST_P(ResourceProviderTest, DestroyChildWithExportedResources) {
1561 gfx::Size size(1, 1);
1562 ResourceFormat format = RGBA_8888;
1563 size_t pixel_size = TextureSizeBytes(size, format);
1564 ASSERT_EQ(4U, pixel_size);
1566 ResourceId id1 = child_resource_provider_->CreateResource(
1567 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
1568 uint8_t data1[4] = {1, 2, 3, 4};
1569 child_resource_provider_->CopyToResource(id1, data1, size);
1571 ResourceId id2 = child_resource_provider_->CreateResource(
1572 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
1573 uint8_t data2[4] = {5, 5, 5, 5};
1574 child_resource_provider_->CopyToResource(id2, data2, size);
1576 ReturnedResourceArray returned_to_child;
1577 int child_id =
1578 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1580 // Transfer some resources to the parent.
1581 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1582 resource_ids_to_transfer.push_back(id1);
1583 resource_ids_to_transfer.push_back(id2);
1584 TransferableResourceArray list;
1585 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1586 &list);
1587 ASSERT_EQ(2u, list.size());
1588 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) {
1589 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
1590 EXPECT_NE(0u, list[1].mailbox_holder.sync_point);
1592 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1593 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
1594 resource_provider_->ReceiveFromChild(child_id, list);
1595 ResourceProvider::ResourceIdSet resource_ids_to_receive;
1596 resource_ids_to_receive.insert(id1);
1597 resource_ids_to_receive.insert(id2);
1598 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1599 resource_ids_to_receive);
1602 EXPECT_EQ(2u, resource_provider_->num_resources());
1603 ResourceProvider::ResourceIdMap resource_map =
1604 resource_provider_->GetChildToParentMap(child_id);
1605 ResourceId mapped_id1 = resource_map[id1];
1606 ResourceId mapped_id2 = resource_map[id2];
1607 EXPECT_NE(0u, mapped_id1);
1608 EXPECT_NE(0u, mapped_id2);
1609 EXPECT_FALSE(resource_provider_->InUseByConsumer(id1));
1610 EXPECT_FALSE(resource_provider_->InUseByConsumer(id2));
1613 // The parent transfers the resources to the grandparent.
1614 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1615 resource_ids_to_transfer.push_back(mapped_id1);
1616 resource_ids_to_transfer.push_back(mapped_id2);
1617 TransferableResourceArray list;
1618 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
1620 ASSERT_EQ(2u, list.size());
1621 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) {
1622 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
1623 EXPECT_NE(0u, list[1].mailbox_holder.sync_point);
1625 EXPECT_TRUE(resource_provider_->InUseByConsumer(id1));
1626 EXPECT_TRUE(resource_provider_->InUseByConsumer(id2));
1628 // Release the resource in the parent. Set no resources as being in use. The
1629 // resources are exported so that can't be transferred back yet.
1630 ResourceProvider::ResourceIdSet no_resources;
1631 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
1633 // Destroy the child, the resources should not be returned yet.
1634 EXPECT_EQ(0u, returned_to_child.size());
1635 EXPECT_EQ(2u, resource_provider_->num_resources());
1637 resource_provider_->DestroyChild(child_id);
1639 EXPECT_EQ(2u, resource_provider_->num_resources());
1640 ASSERT_EQ(0u, returned_to_child.size());
1642 // Return a resource from the grandparent, it should be returned at this
1643 // point.
1644 EXPECT_EQ(2u, list.size());
1645 EXPECT_EQ(mapped_id1, list[0].id);
1646 EXPECT_EQ(mapped_id2, list[1].id);
1647 TransferableResourceArray return_list;
1648 return_list.push_back(list[1]);
1649 list.pop_back();
1650 ReturnedResourceArray returned;
1651 TransferableResource::ReturnResources(return_list, &returned);
1652 resource_provider_->ReceiveReturnsFromParent(returned);
1654 EXPECT_EQ(1u, resource_provider_->num_resources());
1655 ASSERT_EQ(1u, returned_to_child.size());
1656 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) {
1657 EXPECT_NE(0u, returned_to_child[0].sync_point);
1659 EXPECT_FALSE(returned_to_child[0].lost);
1660 returned_to_child.clear();
1662 // Destroy the parent resource provider. The resource that's left should be
1663 // lost at this point, and returned.
1664 resource_provider_ = nullptr;
1665 ASSERT_EQ(1u, returned_to_child.size());
1666 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) {
1667 EXPECT_NE(0u, returned_to_child[0].sync_point);
1669 EXPECT_TRUE(returned_to_child[0].lost);
1673 TEST_P(ResourceProviderTest, DeleteTransferredResources) {
1674 gfx::Size size(1, 1);
1675 ResourceFormat format = RGBA_8888;
1676 size_t pixel_size = TextureSizeBytes(size, format);
1677 ASSERT_EQ(4U, pixel_size);
1679 ResourceId id = child_resource_provider_->CreateResource(
1680 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
1681 uint8_t data[4] = { 1, 2, 3, 4 };
1682 child_resource_provider_->CopyToResource(id, data, size);
1684 ReturnedResourceArray returned_to_child;
1685 int child_id =
1686 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1688 // Transfer some resource to the parent.
1689 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1690 resource_ids_to_transfer.push_back(id);
1691 TransferableResourceArray list;
1692 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1693 &list);
1694 ASSERT_EQ(1u, list.size());
1695 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
1696 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
1697 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id));
1698 resource_provider_->ReceiveFromChild(child_id, list);
1699 ResourceProvider::ResourceIdSet resource_ids_to_receive;
1700 resource_ids_to_receive.insert(id);
1701 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1702 resource_ids_to_receive);
1705 // Delete textures in the child, while they are transfered.
1706 child_resource_provider_->DeleteResource(id);
1707 EXPECT_EQ(1u, child_resource_provider_->num_resources());
1709 EXPECT_EQ(0u, returned_to_child.size());
1711 // Transfer resources back from the parent to the child. Set no resources as
1712 // being in use.
1713 ResourceProvider::ResourceIdSet no_resources;
1714 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
1716 ASSERT_EQ(1u, returned_to_child.size());
1717 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
1718 EXPECT_NE(0u, returned_to_child[0].sync_point);
1719 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
1721 EXPECT_EQ(0u, child_resource_provider_->num_resources());
1724 TEST_P(ResourceProviderTest, UnuseTransferredResources) {
1725 gfx::Size size(1, 1);
1726 ResourceFormat format = RGBA_8888;
1727 size_t pixel_size = TextureSizeBytes(size, format);
1728 ASSERT_EQ(4U, pixel_size);
1730 ResourceId id = child_resource_provider_->CreateResource(
1731 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
1732 uint8_t data[4] = {1, 2, 3, 4};
1733 child_resource_provider_->CopyToResource(id, data, size);
1735 ReturnedResourceArray returned_to_child;
1736 int child_id =
1737 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1738 const ResourceProvider::ResourceIdMap& map =
1739 resource_provider_->GetChildToParentMap(child_id);
1741 // Transfer some resource to the parent.
1742 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1743 resource_ids_to_transfer.push_back(id);
1744 TransferableResourceArray list;
1745 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1746 &list);
1747 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id));
1748 resource_provider_->ReceiveFromChild(child_id, list);
1749 ResourceProvider::ResourceIdSet resource_ids_to_receive;
1750 resource_ids_to_receive.insert(id);
1751 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1752 resource_ids_to_receive);
1754 TransferableResourceArray sent_to_top_level;
1756 // Parent transfers to top-level.
1757 ASSERT_TRUE(map.find(id) != map.end());
1758 ResourceId parent_id = map.find(id)->second;
1759 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1760 resource_ids_to_transfer.push_back(parent_id);
1761 resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1762 &sent_to_top_level);
1763 EXPECT_TRUE(resource_provider_->InUseByConsumer(parent_id));
1766 // Stop using resource.
1767 ResourceProvider::ResourceIdSet empty;
1768 resource_provider_->DeclareUsedResourcesFromChild(child_id, empty);
1769 // Resource is not yet returned to the child, since it's in use by the
1770 // top-level.
1771 EXPECT_TRUE(returned_to_child.empty());
1774 // Send the resource to the parent again.
1775 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1776 resource_ids_to_transfer.push_back(id);
1777 TransferableResourceArray list;
1778 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1779 &list);
1780 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id));
1781 resource_provider_->ReceiveFromChild(child_id, list);
1782 ResourceProvider::ResourceIdSet resource_ids_to_receive;
1783 resource_ids_to_receive.insert(id);
1784 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1785 resource_ids_to_receive);
1788 // Receive returns back from top-level.
1789 ReturnedResourceArray returned;
1790 TransferableResource::ReturnResources(sent_to_top_level, &returned);
1791 resource_provider_->ReceiveReturnsFromParent(returned);
1792 // Resource is still not yet returned to the child, since it's declared used
1793 // in the parent.
1794 EXPECT_TRUE(returned_to_child.empty());
1795 ASSERT_TRUE(map.find(id) != map.end());
1796 ResourceId parent_id = map.find(id)->second;
1797 EXPECT_FALSE(resource_provider_->InUseByConsumer(parent_id));
1800 sent_to_top_level.clear();
1801 // Parent transfers again to top-level.
1802 ASSERT_TRUE(map.find(id) != map.end());
1803 ResourceId parent_id = map.find(id)->second;
1804 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1805 resource_ids_to_transfer.push_back(parent_id);
1806 resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1807 &sent_to_top_level);
1808 EXPECT_TRUE(resource_provider_->InUseByConsumer(parent_id));
1811 // Receive returns back from top-level.
1812 ReturnedResourceArray returned;
1813 TransferableResource::ReturnResources(sent_to_top_level, &returned);
1814 resource_provider_->ReceiveReturnsFromParent(returned);
1815 // Resource is still not yet returned to the child, since it's still
1816 // declared used in the parent.
1817 EXPECT_TRUE(returned_to_child.empty());
1818 ASSERT_TRUE(map.find(id) != map.end());
1819 ResourceId parent_id = map.find(id)->second;
1820 EXPECT_FALSE(resource_provider_->InUseByConsumer(parent_id));
1823 // Stop using resource.
1824 ResourceProvider::ResourceIdSet empty;
1825 resource_provider_->DeclareUsedResourcesFromChild(child_id, empty);
1826 // Resource should have been returned to the child, since it's no longer in
1827 // use by the top-level.
1828 ASSERT_EQ(1u, returned_to_child.size());
1829 EXPECT_EQ(id, returned_to_child[0].id);
1830 EXPECT_EQ(2, returned_to_child[0].count);
1831 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
1832 returned_to_child.clear();
1833 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id));
1837 class ResourceProviderTestTextureFilters : public ResourceProviderTest {
1838 public:
1839 static void RunTest(GLenum child_filter, GLenum parent_filter) {
1840 scoped_ptr<TextureStateTrackingContext> child_context_owned(
1841 new TextureStateTrackingContext);
1842 TextureStateTrackingContext* child_context = child_context_owned.get();
1844 FakeOutputSurfaceClient child_output_surface_client;
1845 scoped_ptr<OutputSurface> child_output_surface(
1846 FakeOutputSurface::Create3d(child_context_owned.Pass()));
1847 CHECK(child_output_surface->BindToClient(&child_output_surface_client));
1848 scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
1849 new TestSharedBitmapManager());
1851 scoped_ptr<ResourceProvider> child_resource_provider(
1852 ResourceProvider::Create(child_output_surface.get(),
1853 shared_bitmap_manager.get(), NULL, NULL, 0,
1854 false, 1, false));
1856 scoped_ptr<TextureStateTrackingContext> parent_context_owned(
1857 new TextureStateTrackingContext);
1858 TextureStateTrackingContext* parent_context = parent_context_owned.get();
1860 FakeOutputSurfaceClient parent_output_surface_client;
1861 scoped_ptr<OutputSurface> parent_output_surface(
1862 FakeOutputSurface::Create3d(parent_context_owned.Pass()));
1863 CHECK(parent_output_surface->BindToClient(&parent_output_surface_client));
1865 scoped_ptr<ResourceProvider> parent_resource_provider(
1866 ResourceProvider::Create(parent_output_surface.get(),
1867 shared_bitmap_manager.get(), NULL, NULL, 0,
1868 false, 1, false));
1870 gfx::Size size(1, 1);
1871 ResourceFormat format = RGBA_8888;
1872 int child_texture_id = 1;
1873 int parent_texture_id = 2;
1875 size_t pixel_size = TextureSizeBytes(size, format);
1876 ASSERT_EQ(4U, pixel_size);
1878 ResourceId id = child_resource_provider->CreateResource(
1879 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE,
1880 format);
1882 // The new texture is created with GL_LINEAR.
1883 EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, child_texture_id))
1884 .Times(2); // Once to create and once to allocate.
1885 EXPECT_CALL(*child_context,
1886 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
1887 EXPECT_CALL(*child_context,
1888 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
1889 EXPECT_CALL(
1890 *child_context,
1891 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
1892 EXPECT_CALL(
1893 *child_context,
1894 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
1895 EXPECT_CALL(*child_context,
1896 texParameteri(GL_TEXTURE_2D,
1897 GL_TEXTURE_POOL_CHROMIUM,
1898 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM));
1899 child_resource_provider->AllocateForTesting(id);
1900 Mock::VerifyAndClearExpectations(child_context);
1902 uint8_t data[4] = { 1, 2, 3, 4 };
1904 EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, child_texture_id));
1905 child_resource_provider->CopyToResource(id, data, size);
1906 Mock::VerifyAndClearExpectations(child_context);
1908 // The texture is set to |child_filter| in the child.
1909 EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, child_texture_id));
1910 if (child_filter != GL_LINEAR) {
1911 EXPECT_CALL(
1912 *child_context,
1913 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, child_filter));
1914 EXPECT_CALL(
1915 *child_context,
1916 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, child_filter));
1918 SetResourceFilter(child_resource_provider.get(), id, child_filter);
1919 Mock::VerifyAndClearExpectations(child_context);
1921 ReturnedResourceArray returned_to_child;
1922 int child_id = parent_resource_provider->CreateChild(
1923 GetReturnCallback(&returned_to_child));
1925 // Transfer some resource to the parent.
1926 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1927 resource_ids_to_transfer.push_back(id);
1928 TransferableResourceArray list;
1930 EXPECT_CALL(*child_context,
1931 produceTextureDirectCHROMIUM(_, GL_TEXTURE_2D, _));
1932 EXPECT_CALL(*child_context, insertSyncPoint());
1933 child_resource_provider->PrepareSendToParent(resource_ids_to_transfer,
1934 &list);
1935 Mock::VerifyAndClearExpectations(child_context);
1937 ASSERT_EQ(1u, list.size());
1938 EXPECT_EQ(static_cast<unsigned>(child_filter), list[0].filter);
1940 EXPECT_CALL(*parent_context,
1941 createAndConsumeTextureCHROMIUM(GL_TEXTURE_2D, _))
1942 .WillOnce(Return(parent_texture_id));
1944 parent_resource_provider->ReceiveFromChild(child_id, list);
1946 parent_resource_provider->WaitSyncPointIfNeeded(list[0].id);
1947 ResourceProvider::ScopedReadLockGL lock(parent_resource_provider.get(),
1948 list[0].id);
1950 Mock::VerifyAndClearExpectations(parent_context);
1952 ResourceProvider::ResourceIdSet resource_ids_to_receive;
1953 resource_ids_to_receive.insert(id);
1954 parent_resource_provider->DeclareUsedResourcesFromChild(
1955 child_id, resource_ids_to_receive);
1956 Mock::VerifyAndClearExpectations(parent_context);
1958 ResourceProvider::ResourceIdMap resource_map =
1959 parent_resource_provider->GetChildToParentMap(child_id);
1960 ResourceId mapped_id = resource_map[id];
1961 EXPECT_NE(0u, mapped_id);
1963 // The texture is set to |parent_filter| in the parent.
1964 EXPECT_CALL(*parent_context, bindTexture(GL_TEXTURE_2D, parent_texture_id));
1965 EXPECT_CALL(
1966 *parent_context,
1967 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, parent_filter));
1968 EXPECT_CALL(
1969 *parent_context,
1970 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, parent_filter));
1971 SetResourceFilter(parent_resource_provider.get(), mapped_id, parent_filter);
1972 Mock::VerifyAndClearExpectations(parent_context);
1974 // The texture should be reset to |child_filter| in the parent when it is
1975 // returned, since that is how it was received.
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, child_filter));
1980 EXPECT_CALL(
1981 *parent_context,
1982 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, child_filter));
1985 EXPECT_EQ(0u, returned_to_child.size());
1987 // Transfer resources back from the parent to the child. Set no resources
1988 // as being in use.
1989 ResourceProvider::ResourceIdSet no_resources;
1990 EXPECT_CALL(*parent_context, insertSyncPoint());
1991 parent_resource_provider->DeclareUsedResourcesFromChild(child_id,
1992 no_resources);
1993 Mock::VerifyAndClearExpectations(parent_context);
1995 ASSERT_EQ(1u, returned_to_child.size());
1996 child_resource_provider->ReceiveReturnsFromParent(returned_to_child);
1999 // The child remembers the texture filter is set to |child_filter|.
2000 EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, child_texture_id));
2001 SetResourceFilter(child_resource_provider.get(), id, child_filter);
2002 Mock::VerifyAndClearExpectations(child_context);
2006 TEST_P(ResourceProviderTest, TextureFilters_ChildNearestParentLinear) {
2007 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
2008 return;
2009 ResourceProviderTestTextureFilters::RunTest(GL_NEAREST, GL_LINEAR);
2012 TEST_P(ResourceProviderTest, TextureFilters_ChildLinearParentNearest) {
2013 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
2014 return;
2015 ResourceProviderTestTextureFilters::RunTest(GL_LINEAR, GL_NEAREST);
2018 TEST_P(ResourceProviderTest, TransferMailboxResources) {
2019 // Other mailbox transfers tested elsewhere.
2020 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
2021 return;
2022 unsigned texture = context()->createTexture();
2023 context()->bindTexture(GL_TEXTURE_2D, texture);
2024 uint8_t data[4] = { 1, 2, 3, 4 };
2025 context()->texImage2D(
2026 GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &data);
2027 gpu::Mailbox mailbox;
2028 context()->genMailboxCHROMIUM(mailbox.name);
2029 context()->produceTextureDirectCHROMIUM(texture, GL_TEXTURE_2D, mailbox.name);
2030 uint32 sync_point = context()->insertSyncPoint();
2032 // All the logic below assumes that the sync points are all positive.
2033 EXPECT_LT(0u, sync_point);
2035 uint32 release_sync_point = 0;
2036 bool lost_resource = false;
2037 BlockingTaskRunner* main_thread_task_runner = NULL;
2038 ReleaseCallbackImpl callback = base::Bind(ReleaseCallback,
2039 &release_sync_point,
2040 &lost_resource,
2041 &main_thread_task_runner);
2042 ResourceId resource = resource_provider_->CreateResourceFromTextureMailbox(
2043 TextureMailbox(mailbox, GL_TEXTURE_2D, sync_point),
2044 SingleReleaseCallbackImpl::Create(callback));
2045 EXPECT_EQ(1u, context()->NumTextures());
2046 EXPECT_EQ(0u, release_sync_point);
2048 // Transfer the resource, expect the sync points to be consistent.
2049 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2050 resource_ids_to_transfer.push_back(resource);
2051 TransferableResourceArray list;
2052 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
2053 ASSERT_EQ(1u, list.size());
2054 EXPECT_LE(sync_point, list[0].mailbox_holder.sync_point);
2055 EXPECT_EQ(0,
2056 memcmp(mailbox.name,
2057 list[0].mailbox_holder.mailbox.name,
2058 sizeof(mailbox.name)));
2059 EXPECT_EQ(0u, release_sync_point);
2061 context()->waitSyncPoint(list[0].mailbox_holder.sync_point);
2062 unsigned other_texture =
2063 context()->createAndConsumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
2064 uint8_t test_data[4] = { 0 };
2065 context()->GetPixels(
2066 gfx::Size(1, 1), RGBA_8888, test_data);
2067 EXPECT_EQ(0, memcmp(data, test_data, sizeof(data)));
2069 context()->produceTextureDirectCHROMIUM(other_texture, GL_TEXTURE_2D,
2070 mailbox.name);
2071 context()->deleteTexture(other_texture);
2072 list[0].mailbox_holder.sync_point = context()->insertSyncPoint();
2073 EXPECT_LT(0u, list[0].mailbox_holder.sync_point);
2075 // Receive the resource, then delete it, expect the sync points to be
2076 // consistent.
2077 ReturnedResourceArray returned;
2078 TransferableResource::ReturnResources(list, &returned);
2079 resource_provider_->ReceiveReturnsFromParent(returned);
2080 EXPECT_EQ(1u, context()->NumTextures());
2081 EXPECT_EQ(0u, release_sync_point);
2083 resource_provider_->DeleteResource(resource);
2084 EXPECT_LE(list[0].mailbox_holder.sync_point, release_sync_point);
2085 EXPECT_FALSE(lost_resource);
2086 EXPECT_EQ(main_thread_task_runner_.get(), main_thread_task_runner);
2089 // We're going to do the same thing as above, but testing the case where we
2090 // delete the resource before we receive it back.
2091 sync_point = release_sync_point;
2092 EXPECT_LT(0u, sync_point);
2093 release_sync_point = 0;
2094 resource = resource_provider_->CreateResourceFromTextureMailbox(
2095 TextureMailbox(mailbox, GL_TEXTURE_2D, sync_point),
2096 SingleReleaseCallbackImpl::Create(callback));
2097 EXPECT_EQ(1u, context()->NumTextures());
2098 EXPECT_EQ(0u, release_sync_point);
2100 // Transfer the resource, expect the sync points to be consistent.
2101 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2102 resource_ids_to_transfer.push_back(resource);
2103 TransferableResourceArray list;
2104 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
2105 ASSERT_EQ(1u, list.size());
2106 EXPECT_LE(sync_point, list[0].mailbox_holder.sync_point);
2107 EXPECT_EQ(0,
2108 memcmp(mailbox.name,
2109 list[0].mailbox_holder.mailbox.name,
2110 sizeof(mailbox.name)));
2111 EXPECT_EQ(0u, release_sync_point);
2113 context()->waitSyncPoint(list[0].mailbox_holder.sync_point);
2114 unsigned other_texture =
2115 context()->createAndConsumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
2116 uint8_t test_data[4] = { 0 };
2117 context()->GetPixels(
2118 gfx::Size(1, 1), RGBA_8888, test_data);
2119 EXPECT_EQ(0, memcmp(data, test_data, sizeof(data)));
2121 context()->produceTextureDirectCHROMIUM(other_texture, GL_TEXTURE_2D,
2122 mailbox.name);
2123 context()->deleteTexture(other_texture);
2124 list[0].mailbox_holder.sync_point = context()->insertSyncPoint();
2125 EXPECT_LT(0u, list[0].mailbox_holder.sync_point);
2127 // Delete the resource, which shouldn't do anything.
2128 resource_provider_->DeleteResource(resource);
2129 EXPECT_EQ(1u, context()->NumTextures());
2130 EXPECT_EQ(0u, release_sync_point);
2132 // Then receive the resource which should release the mailbox, expect the
2133 // sync points to be consistent.
2134 ReturnedResourceArray returned;
2135 TransferableResource::ReturnResources(list, &returned);
2136 resource_provider_->ReceiveReturnsFromParent(returned);
2137 EXPECT_LE(list[0].mailbox_holder.sync_point, release_sync_point);
2138 EXPECT_FALSE(lost_resource);
2139 EXPECT_EQ(main_thread_task_runner_.get(), main_thread_task_runner);
2142 context()->waitSyncPoint(release_sync_point);
2143 texture =
2144 context()->createAndConsumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
2145 context()->deleteTexture(texture);
2148 TEST_P(ResourceProviderTest, LostResourceInParent) {
2149 gfx::Size size(1, 1);
2150 ResourceFormat format = RGBA_8888;
2151 ResourceId resource = child_resource_provider_->CreateResource(
2152 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
2153 child_resource_provider_->AllocateForTesting(resource);
2154 // Expect a GL resource to be lost.
2155 bool should_lose_resource =
2156 GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE;
2158 ReturnedResourceArray returned_to_child;
2159 int child_id =
2160 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
2162 // Transfer the resource to the parent.
2163 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2164 resource_ids_to_transfer.push_back(resource);
2165 TransferableResourceArray list;
2166 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
2167 &list);
2168 EXPECT_EQ(1u, list.size());
2170 resource_provider_->ReceiveFromChild(child_id, list);
2171 ResourceProvider::ResourceIdSet resource_ids_to_receive;
2172 resource_ids_to_receive.insert(resource);
2173 resource_provider_->DeclareUsedResourcesFromChild(child_id,
2174 resource_ids_to_receive);
2177 // Lose the output surface in the parent.
2178 resource_provider_->DidLoseOutputSurface();
2181 EXPECT_EQ(0u, returned_to_child.size());
2183 // Transfer resources back from the parent to the child. Set no resources as
2184 // being in use.
2185 ResourceProvider::ResourceIdSet no_resources;
2186 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
2188 // Expect a GL resource to be lost.
2189 ASSERT_EQ(1u, returned_to_child.size());
2190 EXPECT_EQ(should_lose_resource, returned_to_child[0].lost);
2191 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
2192 returned_to_child.clear();
2195 // A GL resource should be lost.
2196 EXPECT_EQ(should_lose_resource, child_resource_provider_->IsLost(resource));
2198 // Lost resources stay in use in the parent forever.
2199 EXPECT_EQ(should_lose_resource,
2200 child_resource_provider_->InUseByConsumer(resource));
2203 TEST_P(ResourceProviderTest, LostResourceInGrandParent) {
2204 gfx::Size size(1, 1);
2205 ResourceFormat format = RGBA_8888;
2206 ResourceId resource = child_resource_provider_->CreateResource(
2207 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
2208 child_resource_provider_->AllocateForTesting(resource);
2210 ReturnedResourceArray returned_to_child;
2211 int child_id =
2212 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
2214 // Transfer the resource to the parent.
2215 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2216 resource_ids_to_transfer.push_back(resource);
2217 TransferableResourceArray list;
2218 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
2219 &list);
2220 EXPECT_EQ(1u, list.size());
2222 resource_provider_->ReceiveFromChild(child_id, list);
2223 ResourceProvider::ResourceIdSet resource_ids_to_receive;
2224 resource_ids_to_receive.insert(resource);
2225 resource_provider_->DeclareUsedResourcesFromChild(child_id,
2226 resource_ids_to_receive);
2230 ResourceProvider::ResourceIdMap resource_map =
2231 resource_provider_->GetChildToParentMap(child_id);
2232 ResourceId parent_resource = resource_map[resource];
2233 EXPECT_NE(0u, parent_resource);
2235 // Transfer to a grandparent.
2236 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2237 resource_ids_to_transfer.push_back(parent_resource);
2238 TransferableResourceArray list;
2239 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
2241 // Receive back a lost resource from the grandparent.
2242 EXPECT_EQ(1u, list.size());
2243 EXPECT_EQ(parent_resource, list[0].id);
2244 ReturnedResourceArray returned;
2245 TransferableResource::ReturnResources(list, &returned);
2246 EXPECT_EQ(1u, returned.size());
2247 EXPECT_EQ(parent_resource, returned[0].id);
2248 returned[0].lost = true;
2249 resource_provider_->ReceiveReturnsFromParent(returned);
2251 // The resource should be lost.
2252 EXPECT_TRUE(resource_provider_->IsLost(parent_resource));
2254 // Lost resources stay in use in the parent forever.
2255 EXPECT_TRUE(resource_provider_->InUseByConsumer(parent_resource));
2259 EXPECT_EQ(0u, returned_to_child.size());
2261 // Transfer resources back from the parent to the child. Set no resources as
2262 // being in use.
2263 ResourceProvider::ResourceIdSet no_resources;
2264 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
2266 // Expect the resource to be lost.
2267 ASSERT_EQ(1u, returned_to_child.size());
2268 EXPECT_TRUE(returned_to_child[0].lost);
2269 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
2270 returned_to_child.clear();
2273 // The resource should be lost.
2274 EXPECT_TRUE(child_resource_provider_->IsLost(resource));
2276 // Lost resources stay in use in the parent forever.
2277 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(resource));
2280 TEST_P(ResourceProviderTest, LostMailboxInParent) {
2281 uint32 release_sync_point = 0;
2282 bool lost_resource = false;
2283 bool release_called = false;
2284 uint32 sync_point = 0;
2285 ResourceId resource = CreateChildMailbox(&release_sync_point, &lost_resource,
2286 &release_called, &sync_point);
2288 ReturnedResourceArray returned_to_child;
2289 int child_id =
2290 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
2292 // Transfer the resource to the parent.
2293 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2294 resource_ids_to_transfer.push_back(resource);
2295 TransferableResourceArray list;
2296 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
2297 &list);
2298 EXPECT_EQ(1u, list.size());
2300 resource_provider_->ReceiveFromChild(child_id, list);
2301 ResourceProvider::ResourceIdSet resource_ids_to_receive;
2302 resource_ids_to_receive.insert(resource);
2303 resource_provider_->DeclareUsedResourcesFromChild(child_id,
2304 resource_ids_to_receive);
2307 // Lose the output surface in the parent.
2308 resource_provider_->DidLoseOutputSurface();
2311 EXPECT_EQ(0u, returned_to_child.size());
2313 // Transfer resources back from the parent to the child. Set no resources as
2314 // being in use.
2315 ResourceProvider::ResourceIdSet no_resources;
2316 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
2318 ASSERT_EQ(1u, returned_to_child.size());
2319 // Losing an output surface only loses hardware resources.
2320 EXPECT_EQ(returned_to_child[0].lost,
2321 GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE);
2322 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
2323 returned_to_child.clear();
2326 // Delete the resource in the child. Expect the resource to be lost if it's
2327 // a GL texture.
2328 child_resource_provider_->DeleteResource(resource);
2329 EXPECT_EQ(lost_resource,
2330 GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE);
2333 TEST_P(ResourceProviderTest, LostMailboxInGrandParent) {
2334 uint32 release_sync_point = 0;
2335 bool lost_resource = false;
2336 bool release_called = false;
2337 uint32 sync_point = 0;
2338 ResourceId resource = CreateChildMailbox(&release_sync_point, &lost_resource,
2339 &release_called, &sync_point);
2341 ReturnedResourceArray returned_to_child;
2342 int child_id =
2343 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
2345 // Transfer the resource to the parent.
2346 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2347 resource_ids_to_transfer.push_back(resource);
2348 TransferableResourceArray list;
2349 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
2350 &list);
2351 EXPECT_EQ(1u, list.size());
2353 resource_provider_->ReceiveFromChild(child_id, list);
2354 ResourceProvider::ResourceIdSet resource_ids_to_receive;
2355 resource_ids_to_receive.insert(resource);
2356 resource_provider_->DeclareUsedResourcesFromChild(child_id,
2357 resource_ids_to_receive);
2361 ResourceProvider::ResourceIdMap resource_map =
2362 resource_provider_->GetChildToParentMap(child_id);
2363 ResourceId parent_resource = resource_map[resource];
2364 EXPECT_NE(0u, parent_resource);
2366 // Transfer to a grandparent.
2367 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2368 resource_ids_to_transfer.push_back(parent_resource);
2369 TransferableResourceArray list;
2370 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
2372 // Receive back a lost resource from the grandparent.
2373 EXPECT_EQ(1u, list.size());
2374 EXPECT_EQ(parent_resource, list[0].id);
2375 ReturnedResourceArray returned;
2376 TransferableResource::ReturnResources(list, &returned);
2377 EXPECT_EQ(1u, returned.size());
2378 EXPECT_EQ(parent_resource, returned[0].id);
2379 returned[0].lost = true;
2380 resource_provider_->ReceiveReturnsFromParent(returned);
2384 EXPECT_EQ(0u, returned_to_child.size());
2386 // Transfer resources back from the parent to the child. Set no resources as
2387 // being in use.
2388 ResourceProvider::ResourceIdSet no_resources;
2389 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
2391 // Expect the resource to be lost.
2392 ASSERT_EQ(1u, returned_to_child.size());
2393 EXPECT_TRUE(returned_to_child[0].lost);
2394 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
2395 returned_to_child.clear();
2398 // Delete the resource in the child. Expect the resource to be lost.
2399 child_resource_provider_->DeleteResource(resource);
2400 EXPECT_TRUE(lost_resource);
2403 TEST_P(ResourceProviderTest, Shutdown) {
2404 uint32 release_sync_point = 0;
2405 bool lost_resource = false;
2406 bool release_called = false;
2407 uint32 sync_point = 0;
2408 CreateChildMailbox(
2409 &release_sync_point, &lost_resource, &release_called, &sync_point);
2411 EXPECT_EQ(0u, release_sync_point);
2412 EXPECT_FALSE(lost_resource);
2414 child_resource_provider_ = nullptr;
2416 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) {
2417 EXPECT_LE(sync_point, release_sync_point);
2419 EXPECT_TRUE(release_called);
2420 EXPECT_FALSE(lost_resource);
2423 TEST_P(ResourceProviderTest, ShutdownWithExportedResource) {
2424 uint32 release_sync_point = 0;
2425 bool lost_resource = false;
2426 bool release_called = false;
2427 uint32 sync_point = 0;
2428 ResourceId resource = CreateChildMailbox(&release_sync_point, &lost_resource,
2429 &release_called, &sync_point);
2431 // Transfer the resource, so we can't release it properly on shutdown.
2432 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2433 resource_ids_to_transfer.push_back(resource);
2434 TransferableResourceArray list;
2435 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
2436 &list);
2438 EXPECT_EQ(0u, release_sync_point);
2439 EXPECT_FALSE(lost_resource);
2441 child_resource_provider_ = nullptr;
2443 // Since the resource is in the parent, the child considers it lost.
2444 EXPECT_EQ(0u, release_sync_point);
2445 EXPECT_TRUE(lost_resource);
2448 TEST_P(ResourceProviderTest, LostContext) {
2449 // TextureMailbox callbacks only exist for GL textures for now.
2450 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
2451 return;
2452 unsigned texture = context()->createTexture();
2453 context()->bindTexture(GL_TEXTURE_2D, texture);
2454 gpu::Mailbox mailbox;
2455 context()->genMailboxCHROMIUM(mailbox.name);
2456 context()->produceTextureDirectCHROMIUM(texture, GL_TEXTURE_2D, mailbox.name);
2457 uint32 sync_point = context()->insertSyncPoint();
2459 EXPECT_LT(0u, sync_point);
2461 uint32 release_sync_point = 0;
2462 bool lost_resource = false;
2463 BlockingTaskRunner* main_thread_task_runner = NULL;
2464 scoped_ptr<SingleReleaseCallbackImpl> callback =
2465 SingleReleaseCallbackImpl::Create(base::Bind(ReleaseCallback,
2466 &release_sync_point,
2467 &lost_resource,
2468 &main_thread_task_runner));
2469 resource_provider_->CreateResourceFromTextureMailbox(
2470 TextureMailbox(mailbox, GL_TEXTURE_2D, sync_point), callback.Pass());
2472 EXPECT_EQ(0u, release_sync_point);
2473 EXPECT_FALSE(lost_resource);
2474 EXPECT_EQ(NULL, main_thread_task_runner);
2476 resource_provider_->DidLoseOutputSurface();
2477 resource_provider_ = nullptr;
2479 EXPECT_LE(sync_point, release_sync_point);
2480 EXPECT_TRUE(lost_resource);
2481 EXPECT_EQ(main_thread_task_runner_.get(), main_thread_task_runner);
2484 TEST_P(ResourceProviderTest, ScopedSampler) {
2485 // Sampling is only supported for GL textures.
2486 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
2487 return;
2489 scoped_ptr<TextureStateTrackingContext> context_owned(
2490 new TextureStateTrackingContext);
2491 TextureStateTrackingContext* context = context_owned.get();
2493 FakeOutputSurfaceClient output_surface_client;
2494 scoped_ptr<OutputSurface> output_surface(
2495 FakeOutputSurface::Create3d(context_owned.Pass()));
2496 CHECK(output_surface->BindToClient(&output_surface_client));
2498 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
2499 output_surface.get(), shared_bitmap_manager_.get(),
2500 gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false));
2502 gfx::Size size(1, 1);
2503 ResourceFormat format = RGBA_8888;
2504 int texture_id = 1;
2506 ResourceId id = resource_provider->CreateResource(
2507 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
2509 // Check that the texture gets created with the right sampler settings.
2510 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id))
2511 .Times(2); // Once to create and once to allocate.
2512 EXPECT_CALL(*context,
2513 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
2514 EXPECT_CALL(*context,
2515 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
2516 EXPECT_CALL(
2517 *context,
2518 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
2519 EXPECT_CALL(
2520 *context,
2521 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
2522 EXPECT_CALL(*context,
2523 texParameteri(GL_TEXTURE_2D,
2524 GL_TEXTURE_POOL_CHROMIUM,
2525 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM));
2527 resource_provider->AllocateForTesting(id);
2528 Mock::VerifyAndClearExpectations(context);
2530 // Creating a sampler with the default filter should not change any texture
2531 // parameters.
2533 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
2534 ResourceProvider::ScopedSamplerGL sampler(
2535 resource_provider.get(), id, GL_TEXTURE_2D, GL_LINEAR);
2536 Mock::VerifyAndClearExpectations(context);
2539 // Using a different filter should be reflected in the texture parameters.
2541 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
2542 EXPECT_CALL(
2543 *context,
2544 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
2545 EXPECT_CALL(
2546 *context,
2547 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
2548 ResourceProvider::ScopedSamplerGL sampler(
2549 resource_provider.get(), id, GL_TEXTURE_2D, GL_NEAREST);
2550 Mock::VerifyAndClearExpectations(context);
2553 // Test resetting to the default filter.
2555 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
2556 EXPECT_CALL(*context,
2557 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
2558 EXPECT_CALL(*context,
2559 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
2560 ResourceProvider::ScopedSamplerGL sampler(
2561 resource_provider.get(), id, GL_TEXTURE_2D, GL_LINEAR);
2562 Mock::VerifyAndClearExpectations(context);
2566 TEST_P(ResourceProviderTest, ManagedResource) {
2567 // Sampling is only supported for GL textures.
2568 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
2569 return;
2571 scoped_ptr<TextureStateTrackingContext> context_owned(
2572 new TextureStateTrackingContext);
2573 TextureStateTrackingContext* context = context_owned.get();
2575 FakeOutputSurfaceClient output_surface_client;
2576 scoped_ptr<OutputSurface> output_surface(
2577 FakeOutputSurface::Create3d(context_owned.Pass()));
2578 CHECK(output_surface->BindToClient(&output_surface_client));
2580 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
2581 output_surface.get(), shared_bitmap_manager_.get(),
2582 gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false));
2584 gfx::Size size(1, 1);
2585 ResourceFormat format = RGBA_8888;
2586 int texture_id = 1;
2588 // Check that the texture gets created with the right sampler settings.
2589 ResourceId id = resource_provider->CreateManagedResource(
2590 size, GL_TEXTURE_2D, GL_CLAMP_TO_EDGE,
2591 ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
2592 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
2593 EXPECT_CALL(*context,
2594 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
2595 EXPECT_CALL(*context,
2596 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
2597 EXPECT_CALL(
2598 *context,
2599 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
2600 EXPECT_CALL(
2601 *context,
2602 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
2603 EXPECT_CALL(*context,
2604 texParameteri(GL_TEXTURE_2D,
2605 GL_TEXTURE_POOL_CHROMIUM,
2606 GL_TEXTURE_POOL_MANAGED_CHROMIUM));
2607 resource_provider->CreateForTesting(id);
2608 EXPECT_NE(0u, id);
2610 Mock::VerifyAndClearExpectations(context);
2613 TEST_P(ResourceProviderTest, TextureWrapMode) {
2614 // Sampling is only supported for GL textures.
2615 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
2616 return;
2618 scoped_ptr<TextureStateTrackingContext> context_owned(
2619 new TextureStateTrackingContext);
2620 TextureStateTrackingContext* context = context_owned.get();
2622 FakeOutputSurfaceClient output_surface_client;
2623 scoped_ptr<OutputSurface> output_surface(
2624 FakeOutputSurface::Create3d(context_owned.Pass()));
2625 CHECK(output_surface->BindToClient(&output_surface_client));
2627 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
2628 output_surface.get(), shared_bitmap_manager_.get(),
2629 gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false));
2631 gfx::Size size(1, 1);
2632 ResourceFormat format = RGBA_8888;
2633 GLenum texture_pool = GL_TEXTURE_POOL_UNMANAGED_CHROMIUM;
2635 for (int texture_id = 1; texture_id <= 2; ++texture_id) {
2636 GLint wrap_mode = texture_id == 1 ? GL_CLAMP_TO_EDGE : GL_REPEAT;
2637 // Check that the texture gets created with the right sampler settings.
2638 ResourceId id = resource_provider->CreateGLTexture(
2639 size, GL_TEXTURE_2D, texture_pool, wrap_mode,
2640 ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
2641 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
2642 EXPECT_CALL(*context,
2643 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
2644 EXPECT_CALL(*context,
2645 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
2646 EXPECT_CALL(*context,
2647 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap_mode));
2648 EXPECT_CALL(*context,
2649 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap_mode));
2650 EXPECT_CALL(*context,
2651 texParameteri(GL_TEXTURE_2D,
2652 GL_TEXTURE_POOL_CHROMIUM,
2653 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM));
2654 resource_provider->CreateForTesting(id);
2655 EXPECT_NE(0u, id);
2657 Mock::VerifyAndClearExpectations(context);
2661 TEST_P(ResourceProviderTest, TextureHint) {
2662 // Sampling is only supported for GL textures.
2663 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
2664 return;
2666 scoped_ptr<TextureStateTrackingContext> context_owned(
2667 new TextureStateTrackingContext);
2668 TextureStateTrackingContext* context = context_owned.get();
2669 context->set_support_texture_storage(true);
2670 context->set_support_texture_usage(true);
2672 FakeOutputSurfaceClient output_surface_client;
2673 scoped_ptr<OutputSurface> output_surface(
2674 FakeOutputSurface::Create3d(context_owned.Pass()));
2675 CHECK(output_surface->BindToClient(&output_surface_client));
2677 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
2678 output_surface.get(), shared_bitmap_manager_.get(),
2679 gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false));
2681 gfx::Size size(1, 1);
2682 ResourceFormat format = RGBA_8888;
2683 GLenum texture_pool = GL_TEXTURE_POOL_UNMANAGED_CHROMIUM;
2685 const ResourceProvider::TextureHint hints[4] = {
2686 ResourceProvider::TEXTURE_HINT_DEFAULT,
2687 ResourceProvider::TEXTURE_HINT_IMMUTABLE,
2688 ResourceProvider::TEXTURE_HINT_FRAMEBUFFER,
2689 ResourceProvider::TEXTURE_HINT_IMMUTABLE_FRAMEBUFFER,
2691 for (GLuint texture_id = 1; texture_id <= arraysize(hints); ++texture_id) {
2692 // Check that the texture gets created with the right sampler settings.
2693 ResourceId id = resource_provider->CreateGLTexture(
2694 size, GL_TEXTURE_2D, texture_pool, GL_CLAMP_TO_EDGE,
2695 hints[texture_id - 1], format);
2696 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
2697 EXPECT_CALL(*context,
2698 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
2699 EXPECT_CALL(*context,
2700 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
2701 EXPECT_CALL(
2702 *context,
2703 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
2704 EXPECT_CALL(
2705 *context,
2706 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
2707 EXPECT_CALL(*context,
2708 texParameteri(GL_TEXTURE_2D,
2709 GL_TEXTURE_POOL_CHROMIUM,
2710 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM));
2711 // Check only TEXTURE_HINT_FRAMEBUFFER set GL_TEXTURE_USAGE_ANGLE.
2712 bool is_framebuffer_hint =
2713 hints[texture_id - 1] & ResourceProvider::TEXTURE_HINT_FRAMEBUFFER;
2714 EXPECT_CALL(*context,
2715 texParameteri(GL_TEXTURE_2D,
2716 GL_TEXTURE_USAGE_ANGLE,
2717 GL_FRAMEBUFFER_ATTACHMENT_ANGLE))
2718 .Times(is_framebuffer_hint ? 1 : 0);
2719 resource_provider->CreateForTesting(id);
2720 EXPECT_NE(0u, id);
2722 Mock::VerifyAndClearExpectations(context);
2726 TEST_P(ResourceProviderTest, TextureMailbox_SharedMemory) {
2727 if (GetParam() != ResourceProvider::RESOURCE_TYPE_BITMAP)
2728 return;
2730 gfx::Size size(64, 64);
2731 const uint32_t kBadBeef = 0xbadbeef;
2732 scoped_ptr<SharedBitmap> shared_bitmap(
2733 CreateAndFillSharedBitmap(shared_bitmap_manager_.get(), size, kBadBeef));
2735 FakeOutputSurfaceClient output_surface_client;
2736 scoped_ptr<OutputSurface> output_surface(
2737 FakeOutputSurface::CreateSoftware(make_scoped_ptr(
2738 new SoftwareOutputDevice)));
2739 CHECK(output_surface->BindToClient(&output_surface_client));
2741 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
2742 output_surface.get(), shared_bitmap_manager_.get(),
2743 gpu_memory_buffer_manager_.get(), main_thread_task_runner_.get(), 0,
2744 false, 1, false));
2746 uint32 release_sync_point = 0;
2747 bool lost_resource = false;
2748 BlockingTaskRunner* main_thread_task_runner = NULL;
2749 scoped_ptr<SingleReleaseCallbackImpl> callback =
2750 SingleReleaseCallbackImpl::Create(base::Bind(&ReleaseCallback,
2751 &release_sync_point,
2752 &lost_resource,
2753 &main_thread_task_runner));
2754 TextureMailbox mailbox(shared_bitmap.get(), size);
2756 ResourceId id = resource_provider->CreateResourceFromTextureMailbox(
2757 mailbox, callback.Pass());
2758 EXPECT_NE(0u, id);
2761 ResourceProvider::ScopedReadLockSoftware lock(resource_provider.get(), id);
2762 const SkBitmap* sk_bitmap = lock.sk_bitmap();
2763 EXPECT_EQ(sk_bitmap->width(), size.width());
2764 EXPECT_EQ(sk_bitmap->height(), size.height());
2765 EXPECT_EQ(*sk_bitmap->getAddr32(16, 16), kBadBeef);
2768 resource_provider->DeleteResource(id);
2769 EXPECT_EQ(0u, release_sync_point);
2770 EXPECT_FALSE(lost_resource);
2771 EXPECT_EQ(main_thread_task_runner_.get(), main_thread_task_runner);
2774 class ResourceProviderTestTextureMailboxGLFilters
2775 : public ResourceProviderTest {
2776 public:
2777 static void RunTest(TestSharedBitmapManager* shared_bitmap_manager,
2778 TestGpuMemoryBufferManager* gpu_memory_buffer_manager,
2779 BlockingTaskRunner* main_thread_task_runner,
2780 bool mailbox_nearest_neighbor,
2781 GLenum sampler_filter) {
2782 scoped_ptr<TextureStateTrackingContext> context_owned(
2783 new TextureStateTrackingContext);
2784 TextureStateTrackingContext* context = context_owned.get();
2786 FakeOutputSurfaceClient output_surface_client;
2787 scoped_ptr<OutputSurface> output_surface(
2788 FakeOutputSurface::Create3d(context_owned.Pass()));
2789 CHECK(output_surface->BindToClient(&output_surface_client));
2791 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
2792 output_surface.get(), shared_bitmap_manager, gpu_memory_buffer_manager,
2793 main_thread_task_runner, 0, false, 1, false));
2795 unsigned texture_id = 1;
2796 uint32 sync_point = 30;
2797 unsigned target = GL_TEXTURE_2D;
2799 EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
2800 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
2801 EXPECT_CALL(*context, insertSyncPoint()).Times(0);
2802 EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _, _)).Times(0);
2803 EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(_, _)).Times(0);
2805 gpu::Mailbox gpu_mailbox;
2806 memcpy(gpu_mailbox.name, "Hello world", strlen("Hello world") + 1);
2807 uint32 release_sync_point = 0;
2808 bool lost_resource = false;
2809 BlockingTaskRunner* mailbox_task_runner = NULL;
2810 scoped_ptr<SingleReleaseCallbackImpl> callback =
2811 SingleReleaseCallbackImpl::Create(base::Bind(&ReleaseCallback,
2812 &release_sync_point,
2813 &lost_resource,
2814 &mailbox_task_runner));
2816 TextureMailbox mailbox(gpu_mailbox, target, sync_point);
2817 mailbox.set_nearest_neighbor(mailbox_nearest_neighbor);
2819 ResourceId id = resource_provider->CreateResourceFromTextureMailbox(
2820 mailbox, callback.Pass());
2821 EXPECT_NE(0u, id);
2823 Mock::VerifyAndClearExpectations(context);
2826 // Mailbox sync point WaitSyncPoint before using the texture.
2827 EXPECT_CALL(*context, waitSyncPoint(sync_point));
2828 resource_provider->WaitSyncPointIfNeeded(id);
2829 Mock::VerifyAndClearExpectations(context);
2831 EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(target, _))
2832 .WillOnce(Return(texture_id));
2833 EXPECT_CALL(*context, bindTexture(target, texture_id));
2835 EXPECT_CALL(*context, insertSyncPoint()).Times(0);
2836 EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _, _)).Times(0);
2838 // The sampler will reset these if |mailbox_nearest_neighbor| does not
2839 // match |sampler_filter|.
2840 if (mailbox_nearest_neighbor != (sampler_filter == GL_NEAREST)) {
2841 EXPECT_CALL(*context, texParameteri(
2842 GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, sampler_filter));
2843 EXPECT_CALL(*context, texParameteri(
2844 GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, sampler_filter));
2847 ResourceProvider::ScopedSamplerGL lock(
2848 resource_provider.get(), id, sampler_filter);
2849 Mock::VerifyAndClearExpectations(context);
2851 // When done with it, a sync point should be inserted, but no produce is
2852 // necessary.
2853 EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
2854 EXPECT_CALL(*context, insertSyncPoint());
2855 EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _, _)).Times(0);
2857 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
2858 EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(_, _)).Times(0);
2861 resource_provider->DeleteResource(id);
2862 EXPECT_EQ(0u, release_sync_point);
2863 EXPECT_FALSE(lost_resource);
2864 EXPECT_EQ(main_thread_task_runner, mailbox_task_runner);
2868 TEST_P(ResourceProviderTest, TextureMailbox_GLTexture2D_LinearToLinear) {
2869 // Mailboxing is only supported for GL textures.
2870 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
2871 return;
2873 ResourceProviderTestTextureMailboxGLFilters::RunTest(
2874 shared_bitmap_manager_.get(),
2875 gpu_memory_buffer_manager_.get(),
2876 main_thread_task_runner_.get(),
2877 false,
2878 GL_LINEAR);
2881 TEST_P(ResourceProviderTest, TextureMailbox_GLTexture2D_NearestToNearest) {
2882 // Mailboxing is only supported for GL textures.
2883 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
2884 return;
2886 ResourceProviderTestTextureMailboxGLFilters::RunTest(
2887 shared_bitmap_manager_.get(),
2888 gpu_memory_buffer_manager_.get(),
2889 main_thread_task_runner_.get(),
2890 true,
2891 GL_NEAREST);
2894 TEST_P(ResourceProviderTest, TextureMailbox_GLTexture2D_NearestToLinear) {
2895 // Mailboxing is only supported for GL textures.
2896 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
2897 return;
2899 ResourceProviderTestTextureMailboxGLFilters::RunTest(
2900 shared_bitmap_manager_.get(),
2901 gpu_memory_buffer_manager_.get(),
2902 main_thread_task_runner_.get(),
2903 true,
2904 GL_LINEAR);
2907 TEST_P(ResourceProviderTest, TextureMailbox_GLTexture2D_LinearToNearest) {
2908 // Mailboxing is only supported for GL textures.
2909 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
2910 return;
2912 ResourceProviderTestTextureMailboxGLFilters::RunTest(
2913 shared_bitmap_manager_.get(),
2914 gpu_memory_buffer_manager_.get(),
2915 main_thread_task_runner_.get(),
2916 false,
2917 GL_NEAREST);
2920 TEST_P(ResourceProviderTest, TextureMailbox_GLTextureExternalOES) {
2921 // Mailboxing is only supported for GL textures.
2922 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
2923 return;
2925 scoped_ptr<TextureStateTrackingContext> context_owned(
2926 new TextureStateTrackingContext);
2927 TextureStateTrackingContext* context = context_owned.get();
2929 FakeOutputSurfaceClient output_surface_client;
2930 scoped_ptr<OutputSurface> output_surface(
2931 FakeOutputSurface::Create3d(context_owned.Pass()));
2932 CHECK(output_surface->BindToClient(&output_surface_client));
2934 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
2935 output_surface.get(), shared_bitmap_manager_.get(),
2936 gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false));
2938 uint32 sync_point = 30;
2939 unsigned target = GL_TEXTURE_EXTERNAL_OES;
2941 EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
2942 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
2943 EXPECT_CALL(*context, insertSyncPoint()).Times(0);
2944 EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _, _)).Times(0);
2945 EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(_, _)).Times(0);
2947 gpu::Mailbox gpu_mailbox;
2948 memcpy(gpu_mailbox.name, "Hello world", strlen("Hello world") + 1);
2949 scoped_ptr<SingleReleaseCallbackImpl> callback =
2950 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback));
2952 TextureMailbox mailbox(gpu_mailbox, target, sync_point);
2954 ResourceId id = resource_provider->CreateResourceFromTextureMailbox(
2955 mailbox, callback.Pass());
2956 EXPECT_NE(0u, id);
2958 Mock::VerifyAndClearExpectations(context);
2961 // Mailbox sync point WaitSyncPoint before using the texture.
2962 EXPECT_CALL(*context, waitSyncPoint(sync_point));
2963 resource_provider->WaitSyncPointIfNeeded(id);
2964 Mock::VerifyAndClearExpectations(context);
2966 unsigned texture_id = 1;
2968 EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(target, _))
2969 .WillOnce(Return(texture_id));
2971 EXPECT_CALL(*context, insertSyncPoint()).Times(0);
2972 EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _, _)).Times(0);
2974 ResourceProvider::ScopedReadLockGL lock(resource_provider.get(), id);
2975 Mock::VerifyAndClearExpectations(context);
2977 // When done with it, a sync point should be inserted, but no produce is
2978 // necessary.
2979 EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
2980 EXPECT_CALL(*context, insertSyncPoint());
2981 EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _, _)).Times(0);
2983 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
2984 EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(_, _)).Times(0);
2988 TEST_P(ResourceProviderTest,
2989 TextureMailbox_WaitSyncPointIfNeeded_WithSyncPoint) {
2990 // Mailboxing is only supported for GL textures.
2991 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
2992 return;
2994 scoped_ptr<TextureStateTrackingContext> context_owned(
2995 new TextureStateTrackingContext);
2996 TextureStateTrackingContext* context = context_owned.get();
2998 FakeOutputSurfaceClient output_surface_client;
2999 scoped_ptr<OutputSurface> output_surface(
3000 FakeOutputSurface::Create3d(context_owned.Pass()));
3001 CHECK(output_surface->BindToClient(&output_surface_client));
3003 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
3004 output_surface.get(), shared_bitmap_manager_.get(),
3005 gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false));
3007 uint32 sync_point = 30;
3008 unsigned target = GL_TEXTURE_2D;
3010 EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
3011 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
3012 EXPECT_CALL(*context, insertSyncPoint()).Times(0);
3013 EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _, _)).Times(0);
3014 EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(_, _)).Times(0);
3016 gpu::Mailbox gpu_mailbox;
3017 memcpy(gpu_mailbox.name, "Hello world", strlen("Hello world") + 1);
3018 scoped_ptr<SingleReleaseCallbackImpl> callback =
3019 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback));
3021 TextureMailbox mailbox(gpu_mailbox, target, sync_point);
3023 ResourceId id = resource_provider->CreateResourceFromTextureMailbox(
3024 mailbox, callback.Pass());
3025 EXPECT_NE(0u, id);
3027 Mock::VerifyAndClearExpectations(context);
3030 // First call to WaitSyncPointIfNeeded should call waitSyncPoint.
3031 EXPECT_CALL(*context, waitSyncPoint(sync_point));
3032 resource_provider->WaitSyncPointIfNeeded(id);
3033 Mock::VerifyAndClearExpectations(context);
3035 // Subsequent calls to WaitSyncPointIfNeeded shouldn't call waitSyncPoint.
3036 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
3037 resource_provider->WaitSyncPointIfNeeded(id);
3038 Mock::VerifyAndClearExpectations(context);
3042 TEST_P(ResourceProviderTest, TextureMailbox_WaitSyncPointIfNeeded_NoSyncPoint) {
3043 // Mailboxing is only supported for GL textures.
3044 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
3045 return;
3047 scoped_ptr<TextureStateTrackingContext> context_owned(
3048 new TextureStateTrackingContext);
3049 TextureStateTrackingContext* context = context_owned.get();
3051 FakeOutputSurfaceClient output_surface_client;
3052 scoped_ptr<OutputSurface> output_surface(
3053 FakeOutputSurface::Create3d(context_owned.Pass()));
3054 CHECK(output_surface->BindToClient(&output_surface_client));
3056 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
3057 output_surface.get(), shared_bitmap_manager_.get(),
3058 gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false));
3060 uint32 sync_point = 0;
3061 unsigned target = GL_TEXTURE_2D;
3063 EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
3064 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
3065 EXPECT_CALL(*context, insertSyncPoint()).Times(0);
3066 EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _, _)).Times(0);
3067 EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(_, _)).Times(0);
3069 gpu::Mailbox gpu_mailbox;
3070 memcpy(gpu_mailbox.name, "Hello world", strlen("Hello world") + 1);
3071 scoped_ptr<SingleReleaseCallbackImpl> callback =
3072 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback));
3074 TextureMailbox mailbox(gpu_mailbox, target, sync_point);
3076 ResourceId id = resource_provider->CreateResourceFromTextureMailbox(
3077 mailbox, callback.Pass());
3078 EXPECT_NE(0u, id);
3080 Mock::VerifyAndClearExpectations(context);
3083 // WaitSyncPointIfNeeded with sync_point == 0 shouldn't call waitSyncPoint.
3084 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
3085 resource_provider->WaitSyncPointIfNeeded(id);
3086 Mock::VerifyAndClearExpectations(context);
3090 class AllocationTrackingContext3D : public TestWebGraphicsContext3D {
3091 public:
3092 MOCK_METHOD0(NextTextureId, GLuint());
3093 MOCK_METHOD1(RetireTextureId, void(GLuint id));
3094 MOCK_METHOD2(bindTexture, void(GLenum target, GLuint texture));
3095 MOCK_METHOD5(texStorage2DEXT,
3096 void(GLenum target,
3097 GLint levels,
3098 GLuint internalformat,
3099 GLint width,
3100 GLint height));
3101 MOCK_METHOD9(texImage2D,
3102 void(GLenum target,
3103 GLint level,
3104 GLenum internalformat,
3105 GLsizei width,
3106 GLsizei height,
3107 GLint border,
3108 GLenum format,
3109 GLenum type,
3110 const void* pixels));
3111 MOCK_METHOD9(texSubImage2D,
3112 void(GLenum target,
3113 GLint level,
3114 GLint xoffset,
3115 GLint yoffset,
3116 GLsizei width,
3117 GLsizei height,
3118 GLenum format,
3119 GLenum type,
3120 const void* pixels));
3121 MOCK_METHOD9(asyncTexImage2DCHROMIUM,
3122 void(GLenum target,
3123 GLint level,
3124 GLenum internalformat,
3125 GLsizei width,
3126 GLsizei height,
3127 GLint border,
3128 GLenum format,
3129 GLenum type,
3130 const void* pixels));
3131 MOCK_METHOD9(asyncTexSubImage2DCHROMIUM,
3132 void(GLenum target,
3133 GLint level,
3134 GLint xoffset,
3135 GLint yoffset,
3136 GLsizei width,
3137 GLsizei height,
3138 GLenum format,
3139 GLenum type,
3140 const void* pixels));
3141 MOCK_METHOD8(compressedTexImage2D,
3142 void(GLenum target,
3143 GLint level,
3144 GLenum internalformat,
3145 GLsizei width,
3146 GLsizei height,
3147 GLint border,
3148 GLsizei image_size,
3149 const void* data));
3150 MOCK_METHOD1(waitAsyncTexImage2DCHROMIUM, void(GLenum));
3151 MOCK_METHOD4(createImageCHROMIUM,
3152 GLuint(ClientBuffer, GLsizei, GLsizei, GLenum));
3153 MOCK_METHOD1(destroyImageCHROMIUM, void(GLuint));
3154 MOCK_METHOD2(bindTexImage2DCHROMIUM, void(GLenum, GLint));
3155 MOCK_METHOD2(releaseTexImage2DCHROMIUM, void(GLenum, GLint));
3157 // We're mocking bindTexture, so we override
3158 // TestWebGraphicsContext3D::texParameteri to avoid assertions related to the
3159 // currently bound texture.
3160 virtual void texParameteri(GLenum target, GLenum pname, GLint param) {}
3163 TEST_P(ResourceProviderTest, TextureAllocation) {
3164 // Only for GL textures.
3165 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
3166 return;
3167 scoped_ptr<AllocationTrackingContext3D> context_owned(
3168 new StrictMock<AllocationTrackingContext3D>);
3169 AllocationTrackingContext3D* context = context_owned.get();
3171 FakeOutputSurfaceClient output_surface_client;
3172 scoped_ptr<OutputSurface> output_surface(
3173 FakeOutputSurface::Create3d(context_owned.Pass()));
3174 CHECK(output_surface->BindToClient(&output_surface_client));
3176 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
3177 output_surface.get(), shared_bitmap_manager_.get(),
3178 gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false));
3180 gfx::Size size(2, 2);
3181 gfx::Vector2d offset(0, 0);
3182 ResourceFormat format = RGBA_8888;
3183 ResourceId id = 0;
3184 uint8_t pixels[16] = { 0 };
3185 int texture_id = 123;
3187 // Lazy allocation. Don't allocate when creating the resource.
3188 id = resource_provider->CreateResource(
3189 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
3191 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3192 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(1);
3193 resource_provider->CreateForTesting(id);
3195 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3196 resource_provider->DeleteResource(id);
3198 Mock::VerifyAndClearExpectations(context);
3200 // Do allocate when we set the pixels.
3201 id = resource_provider->CreateResource(
3202 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
3204 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3205 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(3);
3206 EXPECT_CALL(*context, texImage2D(_, _, _, 2, 2, _, _, _, _)).Times(1);
3207 EXPECT_CALL(*context, texSubImage2D(_, _, _, _, 2, 2, _, _, _)).Times(1);
3208 resource_provider->CopyToResource(id, pixels, size);
3210 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3211 resource_provider->DeleteResource(id);
3213 Mock::VerifyAndClearExpectations(context);
3215 // Same for async version.
3216 id = resource_provider->CreateResource(
3217 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
3218 resource_provider->AcquirePixelBuffer(id);
3220 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3221 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
3222 EXPECT_CALL(*context, asyncTexImage2DCHROMIUM(_, _, _, 2, 2, _, _, _, _))
3223 .Times(1);
3224 resource_provider->BeginSetPixels(id);
3225 ASSERT_TRUE(resource_provider->DidSetPixelsComplete(id));
3227 resource_provider->ReleasePixelBuffer(id);
3229 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3230 resource_provider->DeleteResource(id);
3232 Mock::VerifyAndClearExpectations(context);
3235 TEST_P(ResourceProviderTest, TextureAllocationHint) {
3236 // Only for GL textures.
3237 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
3238 return;
3239 scoped_ptr<AllocationTrackingContext3D> context_owned(
3240 new StrictMock<AllocationTrackingContext3D>);
3241 AllocationTrackingContext3D* context = context_owned.get();
3242 context->set_support_texture_storage(true);
3243 context->set_support_texture_usage(true);
3245 FakeOutputSurfaceClient output_surface_client;
3246 scoped_ptr<OutputSurface> output_surface(
3247 FakeOutputSurface::Create3d(context_owned.Pass()));
3248 CHECK(output_surface->BindToClient(&output_surface_client));
3250 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
3251 output_surface.get(), shared_bitmap_manager_.get(),
3252 gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false));
3254 gfx::Size size(2, 2);
3256 const ResourceFormat formats[2] = {RGBA_8888, BGRA_8888};
3257 const ResourceProvider::TextureHint hints[4] = {
3258 ResourceProvider::TEXTURE_HINT_DEFAULT,
3259 ResourceProvider::TEXTURE_HINT_IMMUTABLE,
3260 ResourceProvider::TEXTURE_HINT_FRAMEBUFFER,
3261 ResourceProvider::TEXTURE_HINT_IMMUTABLE_FRAMEBUFFER,
3263 for (size_t i = 0; i < arraysize(formats); ++i) {
3264 for (GLuint texture_id = 1; texture_id <= arraysize(hints); ++texture_id) {
3265 // Lazy allocation. Don't allocate when creating the resource.
3266 ResourceId id = resource_provider->CreateResource(
3267 size, GL_CLAMP_TO_EDGE, hints[texture_id - 1], formats[i]);
3269 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3270 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
3271 bool is_immutable_hint =
3272 hints[texture_id - 1] & ResourceProvider::TEXTURE_HINT_IMMUTABLE;
3273 bool support_immutable_texture =
3274 is_immutable_hint && formats[i] == RGBA_8888;
3275 EXPECT_CALL(*context, texStorage2DEXT(_, _, _, 2, 2))
3276 .Times(support_immutable_texture ? 1 : 0);
3277 EXPECT_CALL(*context, texImage2D(_, _, _, 2, 2, _, _, _, _))
3278 .Times(support_immutable_texture ? 0 : 1);
3279 resource_provider->AllocateForTesting(id);
3281 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3282 resource_provider->DeleteResource(id);
3284 Mock::VerifyAndClearExpectations(context);
3289 TEST_P(ResourceProviderTest, TextureAllocationHint_BGRA) {
3290 // Only for GL textures.
3291 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
3292 return;
3293 scoped_ptr<AllocationTrackingContext3D> context_owned(
3294 new StrictMock<AllocationTrackingContext3D>);
3295 AllocationTrackingContext3D* context = context_owned.get();
3296 context->set_support_texture_format_bgra8888(true);
3297 context->set_support_texture_storage(true);
3298 context->set_support_texture_usage(true);
3300 FakeOutputSurfaceClient output_surface_client;
3301 scoped_ptr<OutputSurface> output_surface(
3302 FakeOutputSurface::Create3d(context_owned.Pass()));
3303 CHECK(output_surface->BindToClient(&output_surface_client));
3305 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
3306 output_surface.get(), shared_bitmap_manager_.get(),
3307 gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false));
3309 gfx::Size size(2, 2);
3310 const ResourceFormat formats[2] = {RGBA_8888, BGRA_8888};
3312 const ResourceProvider::TextureHint hints[4] = {
3313 ResourceProvider::TEXTURE_HINT_DEFAULT,
3314 ResourceProvider::TEXTURE_HINT_IMMUTABLE,
3315 ResourceProvider::TEXTURE_HINT_FRAMEBUFFER,
3316 ResourceProvider::TEXTURE_HINT_IMMUTABLE_FRAMEBUFFER,
3318 for (size_t i = 0; i < arraysize(formats); ++i) {
3319 for (GLuint texture_id = 1; texture_id <= arraysize(hints); ++texture_id) {
3320 // Lazy allocation. Don't allocate when creating the resource.
3321 ResourceId id = resource_provider->CreateResource(
3322 size, GL_CLAMP_TO_EDGE, hints[texture_id - 1], formats[i]);
3324 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3325 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
3326 bool is_immutable_hint =
3327 hints[texture_id - 1] & ResourceProvider::TEXTURE_HINT_IMMUTABLE;
3328 EXPECT_CALL(*context, texStorage2DEXT(_, _, _, 2, 2))
3329 .Times(is_immutable_hint ? 1 : 0);
3330 EXPECT_CALL(*context, texImage2D(_, _, _, 2, 2, _, _, _, _))
3331 .Times(is_immutable_hint ? 0 : 1);
3332 resource_provider->AllocateForTesting(id);
3334 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3335 resource_provider->DeleteResource(id);
3337 Mock::VerifyAndClearExpectations(context);
3342 TEST_P(ResourceProviderTest, PixelBuffer_GLTexture) {
3343 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
3344 return;
3345 scoped_ptr<AllocationTrackingContext3D> context_owned(
3346 new StrictMock<AllocationTrackingContext3D>);
3347 AllocationTrackingContext3D* context = context_owned.get();
3349 FakeOutputSurfaceClient output_surface_client;
3350 scoped_ptr<OutputSurface> output_surface(
3351 FakeOutputSurface::Create3d(context_owned.Pass()));
3352 CHECK(output_surface->BindToClient(&output_surface_client));
3354 gfx::Size size(2, 2);
3355 ResourceFormat format = RGBA_8888;
3356 ResourceId id = 0;
3357 int texture_id = 123;
3359 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
3360 output_surface.get(), shared_bitmap_manager_.get(),
3361 gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false));
3363 id = resource_provider->CreateResource(
3364 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
3365 resource_provider->AcquirePixelBuffer(id);
3367 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3368 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
3369 EXPECT_CALL(*context, asyncTexImage2DCHROMIUM(_, _, _, 2, 2, _, _, _, _))
3370 .Times(1);
3371 resource_provider->BeginSetPixels(id);
3373 EXPECT_TRUE(resource_provider->DidSetPixelsComplete(id));
3375 resource_provider->ReleasePixelBuffer(id);
3377 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3378 resource_provider->DeleteResource(id);
3380 Mock::VerifyAndClearExpectations(context);
3383 TEST_P(ResourceProviderTest, ForcingAsyncUploadToComplete) {
3384 // Only for GL textures.
3385 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
3386 return;
3387 scoped_ptr<AllocationTrackingContext3D> context_owned(
3388 new StrictMock<AllocationTrackingContext3D>);
3389 AllocationTrackingContext3D* context = context_owned.get();
3391 FakeOutputSurfaceClient output_surface_client;
3392 scoped_ptr<OutputSurface> output_surface(
3393 FakeOutputSurface::Create3d(context_owned.Pass()));
3394 CHECK(output_surface->BindToClient(&output_surface_client));
3396 gfx::Size size(2, 2);
3397 ResourceFormat format = RGBA_8888;
3398 ResourceId id = 0;
3399 int texture_id = 123;
3401 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
3402 output_surface.get(), shared_bitmap_manager_.get(),
3403 gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false));
3405 id = resource_provider->CreateResource(
3406 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
3407 resource_provider->AcquirePixelBuffer(id);
3409 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3410 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
3411 EXPECT_CALL(*context, asyncTexImage2DCHROMIUM(_, _, _, 2, 2, _, _, _, _))
3412 .Times(1);
3413 resource_provider->BeginSetPixels(id);
3415 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(1);
3416 EXPECT_CALL(*context, waitAsyncTexImage2DCHROMIUM(GL_TEXTURE_2D)).Times(1);
3417 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, 0)).Times(1);
3418 resource_provider->ForceSetPixelsToComplete(id);
3420 resource_provider->ReleasePixelBuffer(id);
3422 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3423 resource_provider->DeleteResource(id);
3425 Mock::VerifyAndClearExpectations(context);
3428 TEST_P(ResourceProviderTest, PixelBufferLostContext) {
3429 scoped_ptr<AllocationTrackingContext3D> context_owned(
3430 new NiceMock<AllocationTrackingContext3D>);
3431 AllocationTrackingContext3D* context = context_owned.get();
3433 FakeOutputSurfaceClient output_surface_client;
3434 scoped_ptr<OutputSurface> output_surface(
3435 FakeOutputSurface::Create3d(context_owned.Pass()));
3436 CHECK(output_surface->BindToClient(&output_surface_client));
3438 gfx::Size size(2, 2);
3439 ResourceFormat format = RGBA_8888;
3440 ResourceId id = 0;
3441 int texture_id = 123;
3443 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
3444 output_surface.get(), shared_bitmap_manager_.get(),
3445 gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false));
3447 EXPECT_CALL(*context, NextTextureId()).WillRepeatedly(Return(texture_id));
3449 id = resource_provider->CreateResource(
3450 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
3451 context->loseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB,
3452 GL_INNOCENT_CONTEXT_RESET_ARB);
3454 resource_provider->AcquirePixelBuffer(id);
3455 int stride;
3456 void* buffer = resource_provider->MapPixelBuffer(id, &stride);
3457 EXPECT_FALSE(buffer);
3458 resource_provider->UnmapPixelBuffer(id);
3459 Mock::VerifyAndClearExpectations(context);
3462 TEST_P(ResourceProviderTest, Image_GLTexture) {
3463 // Only for GL textures.
3464 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
3465 return;
3466 scoped_ptr<AllocationTrackingContext3D> context_owned(
3467 new StrictMock<AllocationTrackingContext3D>);
3468 AllocationTrackingContext3D* context = context_owned.get();
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 const int kWidth = 2;
3476 const int kHeight = 2;
3477 gfx::Size size(kWidth, kHeight);
3478 ResourceFormat format = RGBA_8888;
3479 ResourceId id = 0;
3480 const unsigned kTextureId = 123u;
3481 const unsigned kImageId = 234u;
3483 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
3484 output_surface.get(), shared_bitmap_manager_.get(),
3485 gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false));
3487 id = resource_provider->CreateResource(
3488 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
3490 EXPECT_CALL(*context, NextTextureId())
3491 .WillOnce(Return(kTextureId))
3492 .RetiresOnSaturation();
3493 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kTextureId))
3494 .Times(1)
3495 .RetiresOnSaturation();
3496 EXPECT_CALL(*context, createImageCHROMIUM(_, kWidth, kHeight, GL_RGBA))
3497 .WillOnce(Return(kImageId))
3498 .RetiresOnSaturation();
3500 ResourceProvider::ScopedWriteLockGpuMemoryBuffer lock(
3501 resource_provider.get(), id);
3502 EXPECT_TRUE(lock.GetGpuMemoryBuffer());
3505 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kTextureId))
3506 .Times(1)
3507 .RetiresOnSaturation();
3508 EXPECT_CALL(*context, bindTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId))
3509 .Times(1)
3510 .RetiresOnSaturation();
3512 ResourceProvider::ScopedSamplerGL lock_gl(
3513 resource_provider.get(), id, GL_TEXTURE_2D, GL_LINEAR);
3514 EXPECT_EQ(kTextureId, lock_gl.texture_id());
3518 ResourceProvider::ScopedWriteLockGpuMemoryBuffer lock(
3519 resource_provider.get(), id);
3520 EXPECT_TRUE(lock.GetGpuMemoryBuffer());
3523 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kTextureId)).Times(1)
3524 .RetiresOnSaturation();
3525 EXPECT_CALL(*context, releaseTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId))
3526 .Times(1)
3527 .RetiresOnSaturation();
3528 EXPECT_CALL(*context, bindTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId))
3529 .Times(1)
3530 .RetiresOnSaturation();
3531 EXPECT_CALL(*context, RetireTextureId(kTextureId))
3532 .Times(1)
3533 .RetiresOnSaturation();
3535 ResourceProvider::ScopedSamplerGL lock_gl(
3536 resource_provider.get(), id, GL_TEXTURE_2D, GL_LINEAR);
3537 EXPECT_EQ(kTextureId, lock_gl.texture_id());
3540 EXPECT_CALL(*context, destroyImageCHROMIUM(kImageId))
3541 .Times(1)
3542 .RetiresOnSaturation();
3545 TEST_P(ResourceProviderTest, CopyResource_GLTexture) {
3546 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
3547 return;
3548 scoped_ptr<AllocationTrackingContext3D> context_owned(
3549 new StrictMock<AllocationTrackingContext3D>);
3550 AllocationTrackingContext3D* context = context_owned.get();
3551 context_owned->set_support_sync_query(true);
3553 FakeOutputSurfaceClient output_surface_client;
3554 scoped_ptr<OutputSurface> output_surface(
3555 FakeOutputSurface::Create3d(context_owned.Pass()));
3556 ASSERT_TRUE(output_surface->BindToClient(&output_surface_client));
3558 const int kWidth = 2;
3559 const int kHeight = 2;
3560 gfx::Size size(kWidth, kHeight);
3561 ResourceFormat format = RGBA_8888;
3562 ResourceId source_id = 0;
3563 ResourceId dest_id = 0;
3564 const unsigned kSourceTextureId = 123u;
3565 const unsigned kDestTextureId = 321u;
3566 const unsigned kImageId = 234u;
3568 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
3569 output_surface.get(), shared_bitmap_manager_.get(),
3570 gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false));
3572 source_id = resource_provider->CreateResource(
3573 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
3575 EXPECT_CALL(*context, NextTextureId())
3576 .WillOnce(Return(kSourceTextureId))
3577 .RetiresOnSaturation();
3578 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kSourceTextureId))
3579 .Times(1)
3580 .RetiresOnSaturation();
3581 EXPECT_CALL(*context, createImageCHROMIUM(_, kWidth, kHeight, GL_RGBA))
3582 .WillOnce(Return(kImageId))
3583 .RetiresOnSaturation();
3585 ResourceProvider::ScopedWriteLockGpuMemoryBuffer lock(
3586 resource_provider.get(), source_id);
3587 EXPECT_TRUE(lock.GetGpuMemoryBuffer());
3589 Mock::VerifyAndClearExpectations(context);
3591 dest_id = resource_provider->CreateResource(
3592 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
3594 EXPECT_CALL(*context, NextTextureId())
3595 .WillOnce(Return(kDestTextureId))
3596 .RetiresOnSaturation();
3597 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kDestTextureId))
3598 .Times(2)
3599 .RetiresOnSaturation();
3600 EXPECT_CALL(*context, texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA,
3601 GL_UNSIGNED_BYTE, nullptr))
3602 .Times(1)
3603 .RetiresOnSaturation();
3604 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kSourceTextureId))
3605 .Times(1)
3606 .RetiresOnSaturation();
3607 EXPECT_CALL(*context, bindTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId))
3608 .Times(1)
3609 .RetiresOnSaturation();
3610 resource_provider->CopyResource(source_id, dest_id, gfx::Rect(size));
3611 Mock::VerifyAndClearExpectations(context);
3613 EXPECT_CALL(*context, destroyImageCHROMIUM(kImageId))
3614 .Times(1)
3615 .RetiresOnSaturation();
3616 EXPECT_CALL(*context, RetireTextureId(kSourceTextureId))
3617 .Times(1)
3618 .RetiresOnSaturation();
3619 EXPECT_CALL(*context, RetireTextureId(kDestTextureId))
3620 .Times(1)
3621 .RetiresOnSaturation();
3622 resource_provider->DeleteResource(source_id);
3623 resource_provider->DeleteResource(dest_id);
3626 TEST_P(ResourceProviderTest, CompressedTextureETC1Allocate) {
3627 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
3628 return;
3630 scoped_ptr<AllocationTrackingContext3D> context_owned(
3631 new AllocationTrackingContext3D);
3632 AllocationTrackingContext3D* context = context_owned.get();
3633 context_owned->set_support_compressed_texture_etc1(true);
3635 FakeOutputSurfaceClient output_surface_client;
3636 scoped_ptr<OutputSurface> output_surface(
3637 FakeOutputSurface::Create3d(context_owned.Pass()));
3638 CHECK(output_surface->BindToClient(&output_surface_client));
3640 gfx::Size size(4, 4);
3641 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
3642 output_surface.get(), shared_bitmap_manager_.get(),
3643 gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false));
3644 int texture_id = 123;
3646 ResourceId id = resource_provider->CreateResource(
3647 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, ETC1);
3648 EXPECT_NE(0u, id);
3649 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3650 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
3651 resource_provider->AllocateForTesting(id);
3653 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3654 resource_provider->DeleteResource(id);
3657 TEST_P(ResourceProviderTest, CompressedTextureETC1Upload) {
3658 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
3659 return;
3661 scoped_ptr<AllocationTrackingContext3D> context_owned(
3662 new AllocationTrackingContext3D);
3663 AllocationTrackingContext3D* context = context_owned.get();
3664 context_owned->set_support_compressed_texture_etc1(true);
3666 FakeOutputSurfaceClient output_surface_client;
3667 scoped_ptr<OutputSurface> output_surface(
3668 FakeOutputSurface::Create3d(context_owned.Pass()));
3669 CHECK(output_surface->BindToClient(&output_surface_client));
3671 gfx::Size size(4, 4);
3672 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
3673 output_surface.get(), shared_bitmap_manager_.get(),
3674 gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false));
3675 int texture_id = 123;
3676 uint8_t pixels[8];
3678 ResourceId id = resource_provider->CreateResource(
3679 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, ETC1);
3680 EXPECT_NE(0u, id);
3681 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3682 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(3);
3683 EXPECT_CALL(*context,
3684 compressedTexImage2D(
3685 _, 0, _, size.width(), size.height(), _, _, _)).Times(1);
3686 resource_provider->CopyToResource(id, pixels, size);
3688 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3689 resource_provider->DeleteResource(id);
3692 INSTANTIATE_TEST_CASE_P(
3693 ResourceProviderTests,
3694 ResourceProviderTest,
3695 ::testing::Values(ResourceProvider::RESOURCE_TYPE_GL_TEXTURE,
3696 ResourceProvider::RESOURCE_TYPE_BITMAP));
3698 class TextureIdAllocationTrackingContext : public TestWebGraphicsContext3D {
3699 public:
3700 GLuint NextTextureId() override {
3701 base::AutoLock lock(namespace_->lock);
3702 return namespace_->next_texture_id++;
3704 void RetireTextureId(GLuint) override {}
3705 GLuint PeekTextureId() {
3706 base::AutoLock lock(namespace_->lock);
3707 return namespace_->next_texture_id;
3711 TEST(ResourceProviderTest, TextureAllocationChunkSize) {
3712 scoped_ptr<TextureIdAllocationTrackingContext> context_owned(
3713 new TextureIdAllocationTrackingContext);
3714 TextureIdAllocationTrackingContext* context = context_owned.get();
3716 FakeOutputSurfaceClient output_surface_client;
3717 scoped_ptr<OutputSurface> output_surface(
3718 FakeOutputSurface::Create3d(context_owned.Pass()));
3719 CHECK(output_surface->BindToClient(&output_surface_client));
3720 scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
3721 new TestSharedBitmapManager());
3723 gfx::Size size(1, 1);
3724 ResourceFormat format = RGBA_8888;
3727 size_t kTextureAllocationChunkSize = 1;
3728 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
3729 output_surface.get(), shared_bitmap_manager.get(), NULL, NULL, 0, false,
3730 kTextureAllocationChunkSize, false));
3732 ResourceId id = resource_provider->CreateResource(
3733 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE,
3734 format);
3735 resource_provider->AllocateForTesting(id);
3736 Mock::VerifyAndClearExpectations(context);
3738 DCHECK_EQ(2u, context->PeekTextureId());
3739 resource_provider->DeleteResource(id);
3743 size_t kTextureAllocationChunkSize = 8;
3744 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
3745 output_surface.get(), shared_bitmap_manager.get(), NULL, NULL, 0, false,
3746 kTextureAllocationChunkSize, false));
3748 ResourceId id = resource_provider->CreateResource(
3749 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE,
3750 format);
3751 resource_provider->AllocateForTesting(id);
3752 Mock::VerifyAndClearExpectations(context);
3754 DCHECK_EQ(10u, context->PeekTextureId());
3755 resource_provider->DeleteResource(id);
3759 } // namespace
3760 } // namespace cc