Delete chrome.mediaGalleriesPrivate because the functionality unique to it has since...
[chromium-blink-merge.git] / cc / resources / resource_provider_unittest.cc
blob53741ab30a83a0191ef6d0e99fbe41d5f25ed29c
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_METHOD2(produceTextureCHROMIUM,
101 void(GLenum target, const GLbyte* mailbox));
102 MOCK_METHOD2(consumeTextureCHROMIUM,
103 void(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 produceTextureCHROMIUM(GLenum target, const GLbyte* mailbox) override {
262 CheckTextureIsBound(target);
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 = BoundTexture(target);
271 pending_produce_textures_.push_back(pending.Pass());
274 void consumeTextureCHROMIUM(GLenum target, const GLbyte* mailbox) override {
275 CheckTextureIsBound(target);
276 base::AutoLock lock_for_texture_access(namespace_->lock);
277 scoped_refptr<TestTexture> texture =
278 shared_data_->ConsumeTexture(mailbox, last_waited_sync_point_);
279 namespace_->textures.Replace(BoundTextureId(target), texture);
282 void GetPixels(const gfx::Size& size,
283 ResourceFormat format,
284 uint8_t* pixels) {
285 CheckTextureIsBound(GL_TEXTURE_2D);
286 base::AutoLock lock_for_texture_access(namespace_->lock);
287 scoped_refptr<TestTexture> texture = BoundTexture(GL_TEXTURE_2D);
288 ASSERT_EQ(texture->size, size);
289 ASSERT_EQ(texture->format, format);
290 memcpy(pixels, texture->data.get(), TextureSizeBytes(size, format));
293 protected:
294 explicit ResourceProviderContext(ContextSharedData* shared_data)
295 : shared_data_(shared_data),
296 last_waited_sync_point_(0) {}
298 private:
299 void AllocateTexture(const gfx::Size& size, GLenum format) {
300 CheckTextureIsBound(GL_TEXTURE_2D);
301 ResourceFormat texture_format = RGBA_8888;
302 switch (format) {
303 case GL_RGBA:
304 texture_format = RGBA_8888;
305 break;
306 case GL_BGRA_EXT:
307 texture_format = BGRA_8888;
308 break;
310 base::AutoLock lock_for_texture_access(namespace_->lock);
311 BoundTexture(GL_TEXTURE_2D)->Reallocate(size, texture_format);
314 void SetPixels(int xoffset,
315 int yoffset,
316 int width,
317 int height,
318 const void* pixels) {
319 CheckTextureIsBound(GL_TEXTURE_2D);
320 base::AutoLock lock_for_texture_access(namespace_->lock);
321 scoped_refptr<TestTexture> texture = BoundTexture(GL_TEXTURE_2D);
322 ASSERT_TRUE(texture->data.get());
323 ASSERT_TRUE(xoffset >= 0 && xoffset + width <= texture->size.width());
324 ASSERT_TRUE(yoffset >= 0 && yoffset + height <= texture->size.height());
325 ASSERT_TRUE(pixels);
326 size_t in_pitch = TextureSizeBytes(gfx::Size(width, 1), texture->format);
327 size_t out_pitch =
328 TextureSizeBytes(gfx::Size(texture->size.width(), 1), texture->format);
329 uint8_t* dest = texture->data.get() + yoffset * out_pitch +
330 TextureSizeBytes(gfx::Size(xoffset, 1), texture->format);
331 const uint8_t* src = static_cast<const uint8_t*>(pixels);
332 for (int i = 0; i < height; ++i) {
333 memcpy(dest, src, in_pitch);
334 dest += out_pitch;
335 src += in_pitch;
339 struct PendingProduceTexture {
340 GLbyte mailbox[GL_MAILBOX_SIZE_CHROMIUM];
341 scoped_refptr<TestTexture> texture;
343 typedef ScopedPtrDeque<PendingProduceTexture> PendingProduceTextureList;
344 ContextSharedData* shared_data_;
345 GLuint last_waited_sync_point_;
346 PendingProduceTextureList pending_produce_textures_;
349 void GetResourcePixels(ResourceProvider* resource_provider,
350 ResourceProviderContext* context,
351 ResourceProvider::ResourceId id,
352 const gfx::Size& size,
353 ResourceFormat format,
354 uint8_t* pixels) {
355 resource_provider->WaitSyncPointIfNeeded(id);
356 switch (resource_provider->default_resource_type()) {
357 case ResourceProvider::GLTexture: {
358 ResourceProvider::ScopedReadLockGL lock_gl(resource_provider, id);
359 ASSERT_NE(0U, lock_gl.texture_id());
360 context->bindTexture(GL_TEXTURE_2D, lock_gl.texture_id());
361 context->GetPixels(size, format, pixels);
362 break;
364 case ResourceProvider::Bitmap: {
365 ResourceProvider::ScopedReadLockSoftware lock_software(resource_provider,
366 id);
367 memcpy(pixels,
368 lock_software.sk_bitmap()->getPixels(),
369 lock_software.sk_bitmap()->getSize());
370 break;
372 case ResourceProvider::InvalidType:
373 NOTREACHED();
374 break;
378 class ResourceProviderTest
379 : public testing::TestWithParam<ResourceProvider::ResourceType> {
380 public:
381 ResourceProviderTest()
382 : shared_data_(ContextSharedData::Create()),
383 context3d_(NULL),
384 child_context_(NULL),
385 main_thread_task_runner_(BlockingTaskRunner::Create(NULL)) {
386 switch (GetParam()) {
387 case ResourceProvider::GLTexture: {
388 scoped_ptr<ResourceProviderContext> context3d(
389 ResourceProviderContext::Create(shared_data_.get()));
390 context3d_ = context3d.get();
392 scoped_refptr<TestContextProvider> context_provider =
393 TestContextProvider::Create(context3d.Pass());
395 output_surface_ = FakeOutputSurface::Create3d(context_provider);
397 scoped_ptr<ResourceProviderContext> child_context_owned =
398 ResourceProviderContext::Create(shared_data_.get());
399 child_context_ = child_context_owned.get();
400 child_output_surface_ =
401 FakeOutputSurface::Create3d(child_context_owned.Pass());
402 break;
404 case ResourceProvider::Bitmap:
405 output_surface_ = FakeOutputSurface::CreateSoftware(
406 make_scoped_ptr(new SoftwareOutputDevice));
407 child_output_surface_ = FakeOutputSurface::CreateSoftware(
408 make_scoped_ptr(new SoftwareOutputDevice));
409 break;
410 case ResourceProvider::InvalidType:
411 NOTREACHED();
412 break;
414 CHECK(output_surface_->BindToClient(&output_surface_client_));
415 CHECK(child_output_surface_->BindToClient(&child_output_surface_client_));
417 shared_bitmap_manager_.reset(new TestSharedBitmapManager);
418 gpu_memory_buffer_manager_.reset(new TestGpuMemoryBufferManager);
420 resource_provider_ =
421 ResourceProvider::Create(output_surface_.get(),
422 shared_bitmap_manager_.get(),
423 gpu_memory_buffer_manager_.get(),
424 main_thread_task_runner_.get(),
426 false,
428 child_resource_provider_ =
429 ResourceProvider::Create(child_output_surface_.get(),
430 shared_bitmap_manager_.get(),
431 gpu_memory_buffer_manager_.get(),
432 main_thread_task_runner_.get(),
434 false,
438 static void CollectResources(ReturnedResourceArray* array,
439 const ReturnedResourceArray& returned,
440 BlockingTaskRunner* main_thread_task_runner) {
441 array->insert(array->end(), returned.begin(), returned.end());
444 static ReturnCallback GetReturnCallback(ReturnedResourceArray* array) {
445 return base::Bind(&ResourceProviderTest::CollectResources, array);
448 static void SetResourceFilter(ResourceProvider* resource_provider,
449 ResourceProvider::ResourceId id,
450 GLenum filter) {
451 ResourceProvider::ScopedSamplerGL sampler(
452 resource_provider, id, GL_TEXTURE_2D, filter);
455 ResourceProviderContext* context() { return context3d_; }
457 ResourceProvider::ResourceId CreateChildMailbox(uint32* release_sync_point,
458 bool* lost_resource,
459 bool* release_called,
460 uint32* sync_point) {
461 if (GetParam() == ResourceProvider::GLTexture) {
462 unsigned texture = child_context_->createTexture();
463 gpu::Mailbox gpu_mailbox;
464 child_context_->bindTexture(GL_TEXTURE_2D, texture);
465 child_context_->genMailboxCHROMIUM(gpu_mailbox.name);
466 child_context_->produceTextureCHROMIUM(GL_TEXTURE_2D, gpu_mailbox.name);
467 *sync_point = child_context_->insertSyncPoint();
468 EXPECT_LT(0u, *sync_point);
470 scoped_ptr<SharedBitmap> shared_bitmap;
471 scoped_ptr<SingleReleaseCallbackImpl> callback =
472 SingleReleaseCallbackImpl::Create(base::Bind(
473 ReleaseSharedBitmapCallback, base::Passed(&shared_bitmap),
474 release_called, release_sync_point, lost_resource));
475 return child_resource_provider_->CreateResourceFromTextureMailbox(
476 TextureMailbox(gpu_mailbox, GL_TEXTURE_2D, *sync_point),
477 callback.Pass());
478 } else {
479 gfx::Size size(64, 64);
480 scoped_ptr<SharedBitmap> shared_bitmap(
481 CreateAndFillSharedBitmap(shared_bitmap_manager_.get(), size, 0));
483 SharedBitmap* shared_bitmap_ptr = shared_bitmap.get();
484 scoped_ptr<SingleReleaseCallbackImpl> callback =
485 SingleReleaseCallbackImpl::Create(base::Bind(
486 ReleaseSharedBitmapCallback, base::Passed(&shared_bitmap),
487 release_called, release_sync_point, lost_resource));
488 return child_resource_provider_->CreateResourceFromTextureMailbox(
489 TextureMailbox(shared_bitmap_ptr, size), callback.Pass());
493 protected:
494 scoped_ptr<ContextSharedData> shared_data_;
495 ResourceProviderContext* context3d_;
496 ResourceProviderContext* child_context_;
497 FakeOutputSurfaceClient output_surface_client_;
498 FakeOutputSurfaceClient child_output_surface_client_;
499 scoped_ptr<OutputSurface> output_surface_;
500 scoped_ptr<OutputSurface> child_output_surface_;
501 scoped_ptr<BlockingTaskRunner> main_thread_task_runner_;
502 scoped_ptr<ResourceProvider> resource_provider_;
503 scoped_ptr<ResourceProvider> child_resource_provider_;
504 scoped_ptr<TestSharedBitmapManager> shared_bitmap_manager_;
505 scoped_ptr<TestGpuMemoryBufferManager> gpu_memory_buffer_manager_;
508 void CheckCreateResource(ResourceProvider::ResourceType expected_default_type,
509 ResourceProvider* resource_provider,
510 ResourceProviderContext* context) {
511 DCHECK_EQ(expected_default_type, resource_provider->default_resource_type());
513 gfx::Size size(1, 1);
514 ResourceFormat format = RGBA_8888;
515 size_t pixel_size = TextureSizeBytes(size, format);
516 ASSERT_EQ(4U, pixel_size);
518 ResourceProvider::ResourceId id = resource_provider->CreateResource(
519 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
520 EXPECT_EQ(1, static_cast<int>(resource_provider->num_resources()));
521 if (expected_default_type == ResourceProvider::GLTexture)
522 EXPECT_EQ(0u, context->NumTextures());
524 uint8_t data[4] = { 1, 2, 3, 4 };
525 gfx::Rect rect(size);
526 resource_provider->SetPixels(id, data, rect, rect, gfx::Vector2d());
527 if (expected_default_type == ResourceProvider::GLTexture)
528 EXPECT_EQ(1u, context->NumTextures());
530 uint8_t result[4] = { 0 };
531 GetResourcePixels(resource_provider, context, id, size, format, result);
532 EXPECT_EQ(0, memcmp(data, result, pixel_size));
534 resource_provider->DeleteResource(id);
535 EXPECT_EQ(0, static_cast<int>(resource_provider->num_resources()));
536 if (expected_default_type == ResourceProvider::GLTexture)
537 EXPECT_EQ(0u, context->NumTextures());
540 TEST_P(ResourceProviderTest, Basic) {
541 CheckCreateResource(GetParam(), resource_provider_.get(), context());
544 TEST_P(ResourceProviderTest, Upload) {
545 gfx::Size size(2, 2);
546 ResourceFormat format = RGBA_8888;
547 size_t pixel_size = TextureSizeBytes(size, format);
548 ASSERT_EQ(16U, pixel_size);
550 ResourceProvider::ResourceId id = resource_provider_->CreateResource(
551 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
553 uint8_t image[16] = { 0 };
554 gfx::Rect image_rect(size);
555 resource_provider_->SetPixels(
556 id, image, image_rect, image_rect, gfx::Vector2d());
558 for (uint8_t i = 0; i < pixel_size; ++i)
559 image[i] = i;
561 uint8_t result[16] = { 0 };
563 gfx::Rect source_rect(0, 0, 1, 1);
564 gfx::Vector2d dest_offset(0, 0);
565 resource_provider_->SetPixels(
566 id, image, image_rect, source_rect, dest_offset);
568 uint8_t expected[16] = { 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
569 GetResourcePixels(
570 resource_provider_.get(), context(), id, size, format, result);
571 EXPECT_EQ(0, memcmp(expected, result, pixel_size));
574 gfx::Rect source_rect(0, 0, 1, 1);
575 gfx::Vector2d dest_offset(1, 1);
576 resource_provider_->SetPixels(
577 id, image, image_rect, source_rect, dest_offset);
579 uint8_t expected[16] = { 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3 };
580 GetResourcePixels(
581 resource_provider_.get(), context(), id, size, format, result);
582 EXPECT_EQ(0, memcmp(expected, result, pixel_size));
585 gfx::Rect source_rect(1, 0, 1, 1);
586 gfx::Vector2d dest_offset(0, 1);
587 resource_provider_->SetPixels(
588 id, image, image_rect, source_rect, dest_offset);
590 uint8_t expected[16] = { 0, 1, 2, 3, 0, 0, 0, 0, 4, 5, 6, 7, 0, 1, 2, 3 };
591 GetResourcePixels(
592 resource_provider_.get(), context(), id, size, format, result);
593 EXPECT_EQ(0, memcmp(expected, result, pixel_size));
596 gfx::Rect offset_image_rect(gfx::Point(100, 100), size);
597 gfx::Rect source_rect(100, 100, 1, 1);
598 gfx::Vector2d dest_offset(1, 0);
599 resource_provider_->SetPixels(
600 id, image, offset_image_rect, source_rect, dest_offset);
602 uint8_t expected[16] = { 0, 1, 2, 3, 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3 };
603 GetResourcePixels(
604 resource_provider_.get(), context(), id, size, format, result);
605 EXPECT_EQ(0, memcmp(expected, result, pixel_size));
608 resource_provider_->DeleteResource(id);
611 TEST_P(ResourceProviderTest, TransferGLResources) {
612 if (GetParam() != ResourceProvider::GLTexture)
613 return;
614 gfx::Size size(1, 1);
615 ResourceFormat format = RGBA_8888;
616 size_t pixel_size = TextureSizeBytes(size, format);
617 ASSERT_EQ(4U, pixel_size);
619 ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource(
620 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
621 uint8_t data1[4] = { 1, 2, 3, 4 };
622 gfx::Rect rect(size);
623 child_resource_provider_->SetPixels(id1, data1, rect, rect, gfx::Vector2d());
625 ResourceProvider::ResourceId id2 = child_resource_provider_->CreateResource(
626 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
627 uint8_t data2[4] = { 5, 5, 5, 5 };
628 child_resource_provider_->SetPixels(id2, data2, rect, rect, gfx::Vector2d());
630 ResourceProvider::ResourceId id3 = child_resource_provider_->CreateResource(
631 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
633 ResourceProvider::ScopedWriteLockGpuMemoryBuffer lock(
634 child_resource_provider_.get(), id3);
635 EXPECT_TRUE(!!lock.GetGpuMemoryBuffer());
638 GLuint external_texture_id = child_context_->createExternalTexture();
639 child_context_->bindTexture(GL_TEXTURE_EXTERNAL_OES, external_texture_id);
641 gpu::Mailbox external_mailbox;
642 child_context_->genMailboxCHROMIUM(external_mailbox.name);
643 child_context_->produceTextureCHROMIUM(GL_TEXTURE_EXTERNAL_OES,
644 external_mailbox.name);
645 const GLuint external_sync_point = child_context_->insertSyncPoint();
646 ResourceProvider::ResourceId id4 =
647 child_resource_provider_->CreateResourceFromTextureMailbox(
648 TextureMailbox(
649 external_mailbox, GL_TEXTURE_EXTERNAL_OES, external_sync_point),
650 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback)));
652 ReturnedResourceArray returned_to_child;
653 int child_id =
654 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
656 // Transfer some resources to the parent.
657 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
658 resource_ids_to_transfer.push_back(id1);
659 resource_ids_to_transfer.push_back(id2);
660 resource_ids_to_transfer.push_back(id3);
661 resource_ids_to_transfer.push_back(id4);
662 TransferableResourceArray list;
663 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
664 &list);
665 ASSERT_EQ(4u, list.size());
666 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
667 EXPECT_NE(0u, list[1].mailbox_holder.sync_point);
668 EXPECT_EQ(list[0].mailbox_holder.sync_point,
669 list[1].mailbox_holder.sync_point);
670 EXPECT_NE(0u, list[2].mailbox_holder.sync_point);
671 EXPECT_EQ(list[0].mailbox_holder.sync_point,
672 list[2].mailbox_holder.sync_point);
673 EXPECT_EQ(external_sync_point, list[3].mailbox_holder.sync_point);
674 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
675 list[0].mailbox_holder.texture_target);
676 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
677 list[1].mailbox_holder.texture_target);
678 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
679 list[2].mailbox_holder.texture_target);
680 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_EXTERNAL_OES),
681 list[3].mailbox_holder.texture_target);
682 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
683 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
684 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
685 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id4));
686 resource_provider_->ReceiveFromChild(child_id, list);
687 EXPECT_NE(list[0].mailbox_holder.sync_point,
688 context3d_->last_waited_sync_point());
690 resource_provider_->WaitSyncPointIfNeeded(list[0].id);
691 ResourceProvider::ScopedReadLockGL lock(resource_provider_.get(),
692 list[0].id);
694 EXPECT_EQ(list[0].mailbox_holder.sync_point,
695 context3d_->last_waited_sync_point());
696 resource_provider_->DeclareUsedResourcesFromChild(child_id,
697 resource_ids_to_transfer);
700 EXPECT_EQ(4u, resource_provider_->num_resources());
701 ResourceProvider::ResourceIdMap resource_map =
702 resource_provider_->GetChildToParentMap(child_id);
703 ResourceProvider::ResourceId mapped_id1 = resource_map[id1];
704 ResourceProvider::ResourceId mapped_id2 = resource_map[id2];
705 ResourceProvider::ResourceId mapped_id3 = resource_map[id3];
706 ResourceProvider::ResourceId mapped_id4 = resource_map[id4];
707 EXPECT_NE(0u, mapped_id1);
708 EXPECT_NE(0u, mapped_id2);
709 EXPECT_NE(0u, mapped_id3);
710 EXPECT_NE(0u, mapped_id4);
711 EXPECT_FALSE(resource_provider_->InUseByConsumer(id1));
712 EXPECT_FALSE(resource_provider_->InUseByConsumer(id2));
713 EXPECT_FALSE(resource_provider_->InUseByConsumer(id3));
714 EXPECT_FALSE(resource_provider_->InUseByConsumer(id4));
716 uint8_t result[4] = { 0 };
717 GetResourcePixels(
718 resource_provider_.get(), context(), mapped_id1, size, format, result);
719 EXPECT_EQ(0, memcmp(data1, result, pixel_size));
721 GetResourcePixels(
722 resource_provider_.get(), context(), mapped_id2, size, format, result);
723 EXPECT_EQ(0, memcmp(data2, result, pixel_size));
726 // Check that transfering again the same resource from the child to the
727 // parent works.
728 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
729 resource_ids_to_transfer.push_back(id1);
730 resource_ids_to_transfer.push_back(id2);
731 resource_ids_to_transfer.push_back(id3);
732 TransferableResourceArray list;
733 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
734 &list);
735 EXPECT_EQ(3u, list.size());
736 EXPECT_EQ(id1, list[0].id);
737 EXPECT_EQ(id2, list[1].id);
738 EXPECT_EQ(id3, list[2].id);
739 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
740 list[0].mailbox_holder.texture_target);
741 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
742 list[1].mailbox_holder.texture_target);
743 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
744 list[2].mailbox_holder.texture_target);
745 ReturnedResourceArray returned;
746 TransferableResource::ReturnResources(list, &returned);
747 child_resource_provider_->ReceiveReturnsFromParent(returned);
748 // ids were exported twice, we returned them only once, they should still
749 // be in-use.
750 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
751 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
752 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
755 EXPECT_EQ(0u, returned_to_child.size());
757 // Transfer resources back from the parent to the child. Set no resources as
758 // being in use.
759 ResourceProvider::ResourceIdArray no_resources;
760 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
762 ASSERT_EQ(4u, returned_to_child.size());
763 EXPECT_NE(0u, returned_to_child[0].sync_point);
764 EXPECT_NE(0u, returned_to_child[1].sync_point);
765 EXPECT_NE(0u, returned_to_child[2].sync_point);
766 EXPECT_NE(0u, returned_to_child[3].sync_point);
767 EXPECT_FALSE(returned_to_child[0].lost);
768 EXPECT_FALSE(returned_to_child[1].lost);
769 EXPECT_FALSE(returned_to_child[2].lost);
770 EXPECT_FALSE(returned_to_child[3].lost);
771 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
772 returned_to_child.clear();
774 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id1));
775 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id2));
776 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id3));
777 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id4));
780 child_resource_provider_->WaitSyncPointIfNeeded(id1);
781 ResourceProvider::ScopedReadLockGL lock(child_resource_provider_.get(),
782 id1);
783 ASSERT_NE(0U, lock.texture_id());
784 child_context_->bindTexture(GL_TEXTURE_2D, lock.texture_id());
785 child_context_->GetPixels(size, format, result);
786 EXPECT_EQ(0, memcmp(data1, result, pixel_size));
789 child_resource_provider_->WaitSyncPointIfNeeded(id2);
790 ResourceProvider::ScopedReadLockGL lock(child_resource_provider_.get(),
791 id2);
792 ASSERT_NE(0U, lock.texture_id());
793 child_context_->bindTexture(GL_TEXTURE_2D, lock.texture_id());
794 child_context_->GetPixels(size, format, result);
795 EXPECT_EQ(0, memcmp(data2, result, pixel_size));
798 child_resource_provider_->WaitSyncPointIfNeeded(id3);
799 ResourceProvider::ScopedReadLockGL lock(child_resource_provider_.get(),
800 id3);
801 ASSERT_NE(0U, lock.texture_id());
802 child_context_->bindTexture(GL_TEXTURE_2D, lock.texture_id());
805 // Transfer resources to the parent again.
806 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
807 resource_ids_to_transfer.push_back(id1);
808 resource_ids_to_transfer.push_back(id2);
809 resource_ids_to_transfer.push_back(id3);
810 resource_ids_to_transfer.push_back(id4);
811 TransferableResourceArray list;
812 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
813 &list);
814 ASSERT_EQ(4u, list.size());
815 EXPECT_EQ(id1, list[0].id);
816 EXPECT_EQ(id2, list[1].id);
817 EXPECT_EQ(id3, list[2].id);
818 EXPECT_EQ(id4, list[3].id);
819 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
820 EXPECT_NE(0u, list[1].mailbox_holder.sync_point);
821 EXPECT_NE(0u, list[2].mailbox_holder.sync_point);
822 EXPECT_NE(0u, list[3].mailbox_holder.sync_point);
823 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
824 list[0].mailbox_holder.texture_target);
825 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
826 list[1].mailbox_holder.texture_target);
827 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
828 list[2].mailbox_holder.texture_target);
829 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_EXTERNAL_OES),
830 list[3].mailbox_holder.texture_target);
831 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
832 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
833 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
834 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id4));
835 resource_provider_->ReceiveFromChild(child_id, list);
836 resource_provider_->DeclareUsedResourcesFromChild(child_id,
837 resource_ids_to_transfer);
840 EXPECT_EQ(0u, returned_to_child.size());
842 EXPECT_EQ(4u, resource_provider_->num_resources());
843 resource_provider_->DestroyChild(child_id);
844 EXPECT_EQ(0u, resource_provider_->num_resources());
846 ASSERT_EQ(4u, returned_to_child.size());
847 EXPECT_NE(0u, returned_to_child[0].sync_point);
848 EXPECT_NE(0u, returned_to_child[1].sync_point);
849 EXPECT_NE(0u, returned_to_child[2].sync_point);
850 EXPECT_NE(0u, returned_to_child[3].sync_point);
851 EXPECT_FALSE(returned_to_child[0].lost);
852 EXPECT_FALSE(returned_to_child[1].lost);
853 EXPECT_FALSE(returned_to_child[2].lost);
854 EXPECT_FALSE(returned_to_child[3].lost);
857 TEST_P(ResourceProviderTest, ReadLockCountStopsReturnToChildOrDelete) {
858 if (GetParam() != ResourceProvider::GLTexture)
859 return;
860 gfx::Size size(1, 1);
861 ResourceFormat format = RGBA_8888;
863 ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource(
864 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
865 uint8_t data1[4] = {1, 2, 3, 4};
866 gfx::Rect rect(size);
867 child_resource_provider_->SetPixels(id1, data1, rect, rect, gfx::Vector2d());
869 ReturnedResourceArray returned_to_child;
870 int child_id =
871 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
873 // Transfer some resources to the parent.
874 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
875 resource_ids_to_transfer.push_back(id1);
876 TransferableResourceArray list;
877 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
878 &list);
879 ASSERT_EQ(1u, list.size());
880 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
882 resource_provider_->ReceiveFromChild(child_id, list);
884 resource_provider_->WaitSyncPointIfNeeded(list[0].id);
885 ResourceProvider::ScopedReadLockGL lock(resource_provider_.get(),
886 list[0].id);
888 resource_provider_->DeclareUsedResourcesFromChild(
889 child_id, ResourceProvider::ResourceIdArray());
890 EXPECT_EQ(0u, returned_to_child.size());
893 EXPECT_EQ(1u, returned_to_child.size());
894 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
897 child_resource_provider_->WaitSyncPointIfNeeded(id1);
898 ResourceProvider::ScopedReadLockGL lock(child_resource_provider_.get(),
899 id1);
900 child_resource_provider_->DeleteResource(id1);
901 EXPECT_EQ(1u, child_resource_provider_->num_resources());
902 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
905 EXPECT_EQ(0u, child_resource_provider_->num_resources());
906 resource_provider_->DestroyChild(child_id);
909 TEST_P(ResourceProviderTest, AllowOverlayTransfersToParent) {
910 // Overlays only supported on the GL path.
911 if (GetParam() != ResourceProvider::GLTexture)
912 return;
914 uint32 sync_point = 0;
915 TextureMailbox mailbox(gpu::Mailbox::Generate(), GL_TEXTURE_2D, sync_point);
916 mailbox.set_allow_overlay(true);
917 scoped_ptr<SingleReleaseCallbackImpl> release_callback =
918 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback));
919 ResourceProvider::ResourceId id1 =
920 child_resource_provider_->CreateResourceFromTextureMailbox(
921 mailbox, release_callback.Pass());
923 TextureMailbox mailbox2(gpu::Mailbox::Generate(), GL_TEXTURE_2D, sync_point);
924 mailbox2.set_allow_overlay(false);
925 scoped_ptr<SingleReleaseCallbackImpl> release_callback2 =
926 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback));
927 ResourceProvider::ResourceId id2 =
928 child_resource_provider_->CreateResourceFromTextureMailbox(
929 mailbox2, release_callback2.Pass());
931 ReturnedResourceArray returned_to_child;
932 int child_id =
933 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
935 // Transfer some resources to the parent.
936 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
937 resource_ids_to_transfer.push_back(id1);
938 resource_ids_to_transfer.push_back(id2);
939 TransferableResourceArray list;
940 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
941 &list);
942 ASSERT_EQ(2u, list.size());
943 resource_provider_->ReceiveFromChild(child_id, list);
944 EXPECT_TRUE(resource_provider_->AllowOverlay(list[0].id));
945 EXPECT_FALSE(resource_provider_->AllowOverlay(list[1].id));
947 resource_provider_->DeclareUsedResourcesFromChild(
948 child_id, ResourceProvider::ResourceIdArray());
950 EXPECT_EQ(2u, returned_to_child.size());
951 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
953 child_resource_provider_->DeleteResource(id1);
954 child_resource_provider_->DeleteResource(id2);
955 EXPECT_EQ(0u, child_resource_provider_->num_resources());
957 resource_provider_->DestroyChild(child_id);
960 TEST_P(ResourceProviderTest, TransferSoftwareResources) {
961 if (GetParam() != ResourceProvider::Bitmap)
962 return;
964 gfx::Size size(1, 1);
965 ResourceFormat format = RGBA_8888;
966 size_t pixel_size = TextureSizeBytes(size, format);
967 ASSERT_EQ(4U, pixel_size);
969 ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource(
970 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
971 uint8_t data1[4] = { 1, 2, 3, 4 };
972 gfx::Rect rect(size);
973 child_resource_provider_->SetPixels(id1, data1, rect, rect, gfx::Vector2d());
975 ResourceProvider::ResourceId id2 = child_resource_provider_->CreateResource(
976 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
977 uint8_t data2[4] = { 5, 5, 5, 5 };
978 child_resource_provider_->SetPixels(id2, data2, rect, rect, gfx::Vector2d());
980 scoped_ptr<SharedBitmap> shared_bitmap(CreateAndFillSharedBitmap(
981 shared_bitmap_manager_.get(), gfx::Size(1, 1), 0));
982 SharedBitmap* shared_bitmap_ptr = shared_bitmap.get();
983 ResourceProvider::ResourceId id3 =
984 child_resource_provider_->CreateResourceFromTextureMailbox(
985 TextureMailbox(shared_bitmap_ptr, gfx::Size(1, 1)),
986 SingleReleaseCallbackImpl::Create(base::Bind(
987 &SharedBitmapReleaseCallback, base::Passed(&shared_bitmap))));
989 ReturnedResourceArray returned_to_child;
990 int child_id =
991 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
993 // Transfer some resources to the parent.
994 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
995 resource_ids_to_transfer.push_back(id1);
996 resource_ids_to_transfer.push_back(id2);
997 resource_ids_to_transfer.push_back(id3);
998 TransferableResourceArray list;
999 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1000 &list);
1001 ASSERT_EQ(3u, list.size());
1002 EXPECT_EQ(0u, list[0].mailbox_holder.sync_point);
1003 EXPECT_EQ(0u, list[1].mailbox_holder.sync_point);
1004 EXPECT_EQ(0u, list[2].mailbox_holder.sync_point);
1005 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1006 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
1007 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
1008 resource_provider_->ReceiveFromChild(child_id, list);
1009 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1010 resource_ids_to_transfer);
1013 EXPECT_EQ(3u, resource_provider_->num_resources());
1014 ResourceProvider::ResourceIdMap resource_map =
1015 resource_provider_->GetChildToParentMap(child_id);
1016 ResourceProvider::ResourceId mapped_id1 = resource_map[id1];
1017 ResourceProvider::ResourceId mapped_id2 = resource_map[id2];
1018 ResourceProvider::ResourceId mapped_id3 = resource_map[id3];
1019 EXPECT_NE(0u, mapped_id1);
1020 EXPECT_NE(0u, mapped_id2);
1021 EXPECT_NE(0u, mapped_id3);
1022 EXPECT_FALSE(resource_provider_->InUseByConsumer(id1));
1023 EXPECT_FALSE(resource_provider_->InUseByConsumer(id2));
1024 EXPECT_FALSE(resource_provider_->InUseByConsumer(id3));
1026 uint8_t result[4] = { 0 };
1027 GetResourcePixels(
1028 resource_provider_.get(), context(), mapped_id1, size, format, result);
1029 EXPECT_EQ(0, memcmp(data1, result, pixel_size));
1031 GetResourcePixels(
1032 resource_provider_.get(), context(), mapped_id2, size, format, result);
1033 EXPECT_EQ(0, memcmp(data2, result, pixel_size));
1036 // Check that transfering again the same resource from the child to the
1037 // parent works.
1038 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1039 resource_ids_to_transfer.push_back(id1);
1040 resource_ids_to_transfer.push_back(id2);
1041 TransferableResourceArray list;
1042 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1043 &list);
1044 EXPECT_EQ(2u, list.size());
1045 EXPECT_EQ(id1, list[0].id);
1046 EXPECT_EQ(id2, list[1].id);
1047 ReturnedResourceArray returned;
1048 TransferableResource::ReturnResources(list, &returned);
1049 child_resource_provider_->ReceiveReturnsFromParent(returned);
1050 // ids were exported twice, we returned them only once, they should still
1051 // be in-use.
1052 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1053 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
1056 EXPECT_EQ(0u, returned_to_child.size());
1058 // Transfer resources back from the parent to the child. Set no resources as
1059 // being in use.
1060 ResourceProvider::ResourceIdArray no_resources;
1061 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
1063 ASSERT_EQ(3u, returned_to_child.size());
1064 EXPECT_EQ(0u, returned_to_child[0].sync_point);
1065 EXPECT_EQ(0u, returned_to_child[1].sync_point);
1066 EXPECT_EQ(0u, returned_to_child[2].sync_point);
1067 std::set<ResourceProvider::ResourceId> expected_ids;
1068 expected_ids.insert(id1);
1069 expected_ids.insert(id2);
1070 expected_ids.insert(id3);
1071 std::set<ResourceProvider::ResourceId> returned_ids;
1072 for (unsigned i = 0; i < 3; i++)
1073 returned_ids.insert(returned_to_child[i].id);
1074 EXPECT_EQ(expected_ids, returned_ids);
1075 EXPECT_FALSE(returned_to_child[0].lost);
1076 EXPECT_FALSE(returned_to_child[1].lost);
1077 EXPECT_FALSE(returned_to_child[2].lost);
1078 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
1079 returned_to_child.clear();
1081 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id1));
1082 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id2));
1083 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id3));
1086 ResourceProvider::ScopedReadLockSoftware lock(
1087 child_resource_provider_.get(), id1);
1088 const SkBitmap* sk_bitmap = lock.sk_bitmap();
1089 EXPECT_EQ(sk_bitmap->width(), size.width());
1090 EXPECT_EQ(sk_bitmap->height(), size.height());
1091 EXPECT_EQ(0, memcmp(data1, sk_bitmap->getPixels(), pixel_size));
1094 ResourceProvider::ScopedReadLockSoftware lock(
1095 child_resource_provider_.get(), id2);
1096 const SkBitmap* sk_bitmap = lock.sk_bitmap();
1097 EXPECT_EQ(sk_bitmap->width(), size.width());
1098 EXPECT_EQ(sk_bitmap->height(), size.height());
1099 EXPECT_EQ(0, memcmp(data2, sk_bitmap->getPixels(), pixel_size));
1102 // Transfer resources to the parent again.
1103 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1104 resource_ids_to_transfer.push_back(id1);
1105 resource_ids_to_transfer.push_back(id2);
1106 resource_ids_to_transfer.push_back(id3);
1107 TransferableResourceArray list;
1108 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1109 &list);
1110 ASSERT_EQ(3u, list.size());
1111 EXPECT_EQ(id1, list[0].id);
1112 EXPECT_EQ(id2, list[1].id);
1113 EXPECT_EQ(id3, list[2].id);
1114 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1115 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
1116 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
1117 resource_provider_->ReceiveFromChild(child_id, list);
1118 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1119 resource_ids_to_transfer);
1122 EXPECT_EQ(0u, returned_to_child.size());
1124 EXPECT_EQ(3u, resource_provider_->num_resources());
1125 resource_provider_->DestroyChild(child_id);
1126 EXPECT_EQ(0u, resource_provider_->num_resources());
1128 ASSERT_EQ(3u, returned_to_child.size());
1129 EXPECT_EQ(0u, returned_to_child[0].sync_point);
1130 EXPECT_EQ(0u, returned_to_child[1].sync_point);
1131 EXPECT_EQ(0u, returned_to_child[2].sync_point);
1132 std::set<ResourceProvider::ResourceId> expected_ids;
1133 expected_ids.insert(id1);
1134 expected_ids.insert(id2);
1135 expected_ids.insert(id3);
1136 std::set<ResourceProvider::ResourceId> returned_ids;
1137 for (unsigned i = 0; i < 3; i++)
1138 returned_ids.insert(returned_to_child[i].id);
1139 EXPECT_EQ(expected_ids, returned_ids);
1140 EXPECT_FALSE(returned_to_child[0].lost);
1141 EXPECT_FALSE(returned_to_child[1].lost);
1142 EXPECT_FALSE(returned_to_child[2].lost);
1145 TEST_P(ResourceProviderTest, TransferGLToSoftware) {
1146 if (GetParam() != ResourceProvider::Bitmap)
1147 return;
1149 scoped_ptr<ResourceProviderContext> child_context_owned(
1150 ResourceProviderContext::Create(shared_data_.get()));
1152 FakeOutputSurfaceClient child_output_surface_client;
1153 scoped_ptr<OutputSurface> child_output_surface(
1154 FakeOutputSurface::Create3d(child_context_owned.Pass()));
1155 CHECK(child_output_surface->BindToClient(&child_output_surface_client));
1157 scoped_ptr<ResourceProvider> child_resource_provider(
1158 ResourceProvider::Create(child_output_surface.get(),
1159 shared_bitmap_manager_.get(),
1160 gpu_memory_buffer_manager_.get(),
1161 NULL,
1163 false,
1164 1));
1166 gfx::Size size(1, 1);
1167 ResourceFormat format = RGBA_8888;
1168 size_t pixel_size = TextureSizeBytes(size, format);
1169 ASSERT_EQ(4U, pixel_size);
1171 ResourceProvider::ResourceId id1 = child_resource_provider->CreateResource(
1172 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
1173 uint8_t data1[4] = { 1, 2, 3, 4 };
1174 gfx::Rect rect(size);
1175 child_resource_provider->SetPixels(id1, data1, rect, rect, gfx::Vector2d());
1177 ReturnedResourceArray returned_to_child;
1178 int child_id =
1179 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1181 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1182 resource_ids_to_transfer.push_back(id1);
1183 TransferableResourceArray list;
1184 child_resource_provider->PrepareSendToParent(resource_ids_to_transfer,
1185 &list);
1186 ASSERT_EQ(1u, list.size());
1187 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
1188 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
1189 list[0].mailbox_holder.texture_target);
1190 EXPECT_TRUE(child_resource_provider->InUseByConsumer(id1));
1191 resource_provider_->ReceiveFromChild(child_id, list);
1194 EXPECT_EQ(0u, resource_provider_->num_resources());
1195 ASSERT_EQ(1u, returned_to_child.size());
1196 EXPECT_EQ(returned_to_child[0].id, id1);
1197 ResourceProvider::ResourceIdMap resource_map =
1198 resource_provider_->GetChildToParentMap(child_id);
1199 ResourceProvider::ResourceId mapped_id1 = resource_map[id1];
1200 EXPECT_EQ(0u, mapped_id1);
1202 resource_provider_->DestroyChild(child_id);
1203 EXPECT_EQ(0u, resource_provider_->num_resources());
1205 ASSERT_EQ(1u, returned_to_child.size());
1206 EXPECT_FALSE(returned_to_child[0].lost);
1209 TEST_P(ResourceProviderTest, TransferInvalidSoftware) {
1210 if (GetParam() != ResourceProvider::Bitmap)
1211 return;
1213 gfx::Size size(1, 1);
1214 ResourceFormat format = RGBA_8888;
1215 size_t pixel_size = TextureSizeBytes(size, format);
1216 ASSERT_EQ(4U, pixel_size);
1218 ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource(
1219 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
1220 uint8_t data1[4] = { 1, 2, 3, 4 };
1221 gfx::Rect rect(size);
1222 child_resource_provider_->SetPixels(id1, data1, rect, rect, gfx::Vector2d());
1224 ReturnedResourceArray returned_to_child;
1225 int child_id =
1226 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1228 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1229 resource_ids_to_transfer.push_back(id1);
1230 TransferableResourceArray list;
1231 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1232 &list);
1233 ASSERT_EQ(1u, list.size());
1234 // Make invalid.
1235 list[0].mailbox_holder.mailbox.name[1] = 5;
1236 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1237 resource_provider_->ReceiveFromChild(child_id, list);
1240 EXPECT_EQ(1u, resource_provider_->num_resources());
1241 EXPECT_EQ(0u, returned_to_child.size());
1243 ResourceProvider::ResourceIdMap resource_map =
1244 resource_provider_->GetChildToParentMap(child_id);
1245 ResourceProvider::ResourceId mapped_id1 = resource_map[id1];
1246 EXPECT_NE(0u, mapped_id1);
1248 ResourceProvider::ScopedReadLockSoftware lock(resource_provider_.get(),
1249 mapped_id1);
1250 EXPECT_FALSE(lock.valid());
1253 resource_provider_->DestroyChild(child_id);
1254 EXPECT_EQ(0u, resource_provider_->num_resources());
1256 ASSERT_EQ(1u, returned_to_child.size());
1257 EXPECT_FALSE(returned_to_child[0].lost);
1260 TEST_P(ResourceProviderTest, DeleteExportedResources) {
1261 gfx::Size size(1, 1);
1262 ResourceFormat format = RGBA_8888;
1263 size_t pixel_size = TextureSizeBytes(size, format);
1264 ASSERT_EQ(4U, pixel_size);
1266 ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource(
1267 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
1268 uint8_t data1[4] = { 1, 2, 3, 4 };
1269 gfx::Rect rect(size);
1270 child_resource_provider_->SetPixels(id1, data1, rect, rect, gfx::Vector2d());
1272 ResourceProvider::ResourceId id2 = child_resource_provider_->CreateResource(
1273 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
1274 uint8_t data2[4] = {5, 5, 5, 5};
1275 child_resource_provider_->SetPixels(id2, data2, rect, rect, gfx::Vector2d());
1277 ReturnedResourceArray returned_to_child;
1278 int child_id =
1279 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1281 // Transfer some resources to the parent.
1282 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1283 resource_ids_to_transfer.push_back(id1);
1284 resource_ids_to_transfer.push_back(id2);
1285 TransferableResourceArray list;
1286 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1287 &list);
1288 ASSERT_EQ(2u, list.size());
1289 if (GetParam() == ResourceProvider::GLTexture) {
1290 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
1291 EXPECT_NE(0u, list[1].mailbox_holder.sync_point);
1293 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1294 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
1295 resource_provider_->ReceiveFromChild(child_id, list);
1296 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1297 resource_ids_to_transfer);
1300 EXPECT_EQ(2u, resource_provider_->num_resources());
1301 ResourceProvider::ResourceIdMap resource_map =
1302 resource_provider_->GetChildToParentMap(child_id);
1303 ResourceProvider::ResourceId mapped_id1 = resource_map[id1];
1304 ResourceProvider::ResourceId mapped_id2 = resource_map[id2];
1305 EXPECT_NE(0u, mapped_id1);
1306 EXPECT_NE(0u, mapped_id2);
1307 EXPECT_FALSE(resource_provider_->InUseByConsumer(id1));
1308 EXPECT_FALSE(resource_provider_->InUseByConsumer(id2));
1311 // The parent transfers the resources to the grandparent.
1312 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1313 resource_ids_to_transfer.push_back(mapped_id1);
1314 resource_ids_to_transfer.push_back(mapped_id2);
1315 TransferableResourceArray list;
1316 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
1318 ASSERT_EQ(2u, list.size());
1319 if (GetParam() == ResourceProvider::GLTexture) {
1320 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
1321 EXPECT_NE(0u, list[1].mailbox_holder.sync_point);
1323 EXPECT_TRUE(resource_provider_->InUseByConsumer(id1));
1324 EXPECT_TRUE(resource_provider_->InUseByConsumer(id2));
1326 // Release the resource in the parent. Set no resources as being in use. The
1327 // resources are exported so that can't be transferred back yet.
1328 ResourceProvider::ResourceIdArray no_resources;
1329 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
1331 EXPECT_EQ(0u, returned_to_child.size());
1332 EXPECT_EQ(2u, resource_provider_->num_resources());
1334 // Return the resources from the grandparent to the parent. They should be
1335 // returned to the child then.
1336 EXPECT_EQ(2u, list.size());
1337 EXPECT_EQ(mapped_id1, list[0].id);
1338 EXPECT_EQ(mapped_id2, list[1].id);
1339 ReturnedResourceArray returned;
1340 TransferableResource::ReturnResources(list, &returned);
1341 resource_provider_->ReceiveReturnsFromParent(returned);
1343 EXPECT_EQ(0u, resource_provider_->num_resources());
1344 ASSERT_EQ(2u, returned_to_child.size());
1345 if (GetParam() == ResourceProvider::GLTexture) {
1346 EXPECT_NE(0u, returned_to_child[0].sync_point);
1347 EXPECT_NE(0u, returned_to_child[1].sync_point);
1349 EXPECT_FALSE(returned_to_child[0].lost);
1350 EXPECT_FALSE(returned_to_child[1].lost);
1354 TEST_P(ResourceProviderTest, DestroyChildWithExportedResources) {
1355 gfx::Size size(1, 1);
1356 ResourceFormat format = RGBA_8888;
1357 size_t pixel_size = TextureSizeBytes(size, format);
1358 ASSERT_EQ(4U, pixel_size);
1360 ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource(
1361 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
1362 uint8_t data1[4] = {1, 2, 3, 4};
1363 gfx::Rect rect(size);
1364 child_resource_provider_->SetPixels(id1, data1, rect, rect, gfx::Vector2d());
1366 ResourceProvider::ResourceId id2 = child_resource_provider_->CreateResource(
1367 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
1368 uint8_t data2[4] = {5, 5, 5, 5};
1369 child_resource_provider_->SetPixels(id2, data2, rect, rect, gfx::Vector2d());
1371 ReturnedResourceArray returned_to_child;
1372 int child_id =
1373 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1375 // Transfer some resources to the parent.
1376 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1377 resource_ids_to_transfer.push_back(id1);
1378 resource_ids_to_transfer.push_back(id2);
1379 TransferableResourceArray list;
1380 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1381 &list);
1382 ASSERT_EQ(2u, list.size());
1383 if (GetParam() == ResourceProvider::GLTexture) {
1384 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
1385 EXPECT_NE(0u, list[1].mailbox_holder.sync_point);
1387 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1388 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
1389 resource_provider_->ReceiveFromChild(child_id, list);
1390 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1391 resource_ids_to_transfer);
1394 EXPECT_EQ(2u, resource_provider_->num_resources());
1395 ResourceProvider::ResourceIdMap resource_map =
1396 resource_provider_->GetChildToParentMap(child_id);
1397 ResourceProvider::ResourceId mapped_id1 = resource_map[id1];
1398 ResourceProvider::ResourceId mapped_id2 = resource_map[id2];
1399 EXPECT_NE(0u, mapped_id1);
1400 EXPECT_NE(0u, mapped_id2);
1401 EXPECT_FALSE(resource_provider_->InUseByConsumer(id1));
1402 EXPECT_FALSE(resource_provider_->InUseByConsumer(id2));
1405 // The parent transfers the resources to the grandparent.
1406 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1407 resource_ids_to_transfer.push_back(mapped_id1);
1408 resource_ids_to_transfer.push_back(mapped_id2);
1409 TransferableResourceArray list;
1410 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
1412 ASSERT_EQ(2u, list.size());
1413 if (GetParam() == ResourceProvider::GLTexture) {
1414 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
1415 EXPECT_NE(0u, list[1].mailbox_holder.sync_point);
1417 EXPECT_TRUE(resource_provider_->InUseByConsumer(id1));
1418 EXPECT_TRUE(resource_provider_->InUseByConsumer(id2));
1420 // Release the resource in the parent. Set no resources as being in use. The
1421 // resources are exported so that can't be transferred back yet.
1422 ResourceProvider::ResourceIdArray no_resources;
1423 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
1425 // Destroy the child, the resources should not be returned yet.
1426 EXPECT_EQ(0u, returned_to_child.size());
1427 EXPECT_EQ(2u, resource_provider_->num_resources());
1429 resource_provider_->DestroyChild(child_id);
1431 EXPECT_EQ(2u, resource_provider_->num_resources());
1432 ASSERT_EQ(0u, returned_to_child.size());
1434 // Return a resource from the grandparent, it should be returned at this
1435 // point.
1436 EXPECT_EQ(2u, list.size());
1437 EXPECT_EQ(mapped_id1, list[0].id);
1438 EXPECT_EQ(mapped_id2, list[1].id);
1439 TransferableResourceArray return_list;
1440 return_list.push_back(list[1]);
1441 list.pop_back();
1442 ReturnedResourceArray returned;
1443 TransferableResource::ReturnResources(return_list, &returned);
1444 resource_provider_->ReceiveReturnsFromParent(returned);
1446 EXPECT_EQ(1u, resource_provider_->num_resources());
1447 ASSERT_EQ(1u, returned_to_child.size());
1448 if (GetParam() == ResourceProvider::GLTexture) {
1449 EXPECT_NE(0u, returned_to_child[0].sync_point);
1451 EXPECT_FALSE(returned_to_child[0].lost);
1452 returned_to_child.clear();
1454 // Destroy the parent resource provider. The resource that's left should be
1455 // lost at this point, and returned.
1456 resource_provider_ = nullptr;
1457 ASSERT_EQ(1u, returned_to_child.size());
1458 if (GetParam() == ResourceProvider::GLTexture) {
1459 EXPECT_NE(0u, returned_to_child[0].sync_point);
1461 EXPECT_TRUE(returned_to_child[0].lost);
1465 TEST_P(ResourceProviderTest, DeleteTransferredResources) {
1466 gfx::Size size(1, 1);
1467 ResourceFormat format = RGBA_8888;
1468 size_t pixel_size = TextureSizeBytes(size, format);
1469 ASSERT_EQ(4U, pixel_size);
1471 ResourceProvider::ResourceId id = child_resource_provider_->CreateResource(
1472 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
1473 uint8_t data[4] = { 1, 2, 3, 4 };
1474 gfx::Rect rect(size);
1475 child_resource_provider_->SetPixels(id, data, rect, rect, gfx::Vector2d());
1477 ReturnedResourceArray returned_to_child;
1478 int child_id =
1479 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1481 // Transfer some resource to the parent.
1482 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1483 resource_ids_to_transfer.push_back(id);
1484 TransferableResourceArray list;
1485 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1486 &list);
1487 ASSERT_EQ(1u, list.size());
1488 if (GetParam() == ResourceProvider::GLTexture)
1489 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
1490 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id));
1491 resource_provider_->ReceiveFromChild(child_id, list);
1492 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1493 resource_ids_to_transfer);
1496 // Delete textures in the child, while they are transfered.
1497 child_resource_provider_->DeleteResource(id);
1498 EXPECT_EQ(1u, child_resource_provider_->num_resources());
1500 EXPECT_EQ(0u, returned_to_child.size());
1502 // Transfer resources back from the parent to the child. Set no resources as
1503 // being in use.
1504 ResourceProvider::ResourceIdArray no_resources;
1505 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
1507 ASSERT_EQ(1u, returned_to_child.size());
1508 if (GetParam() == ResourceProvider::GLTexture)
1509 EXPECT_NE(0u, returned_to_child[0].sync_point);
1510 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
1512 EXPECT_EQ(0u, child_resource_provider_->num_resources());
1515 TEST_P(ResourceProviderTest, UnuseTransferredResources) {
1516 gfx::Size size(1, 1);
1517 ResourceFormat format = RGBA_8888;
1518 size_t pixel_size = TextureSizeBytes(size, format);
1519 ASSERT_EQ(4U, pixel_size);
1521 ResourceProvider::ResourceId id = child_resource_provider_->CreateResource(
1522 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
1523 uint8_t data[4] = {1, 2, 3, 4};
1524 gfx::Rect rect(size);
1525 child_resource_provider_->SetPixels(id, data, rect, rect, gfx::Vector2d());
1527 ReturnedResourceArray returned_to_child;
1528 int child_id =
1529 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1530 const ResourceProvider::ResourceIdMap& map =
1531 resource_provider_->GetChildToParentMap(child_id);
1533 // Transfer some resource to the parent.
1534 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1535 resource_ids_to_transfer.push_back(id);
1536 TransferableResourceArray list;
1537 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1538 &list);
1539 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id));
1540 resource_provider_->ReceiveFromChild(child_id, list);
1541 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1542 resource_ids_to_transfer);
1544 TransferableResourceArray sent_to_top_level;
1546 // Parent transfers to top-level.
1547 ASSERT_TRUE(map.find(id) != map.end());
1548 ResourceProvider::ResourceId parent_id = map.find(id)->second;
1549 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1550 resource_ids_to_transfer.push_back(parent_id);
1551 resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1552 &sent_to_top_level);
1553 EXPECT_TRUE(resource_provider_->InUseByConsumer(parent_id));
1556 // Stop using resource.
1557 ResourceProvider::ResourceIdArray empty;
1558 resource_provider_->DeclareUsedResourcesFromChild(child_id, empty);
1559 // Resource is not yet returned to the child, since it's in use by the
1560 // top-level.
1561 EXPECT_TRUE(returned_to_child.empty());
1564 // Send the resource to the parent again.
1565 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1566 resource_ids_to_transfer.push_back(id);
1567 TransferableResourceArray list;
1568 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1569 &list);
1570 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id));
1571 resource_provider_->ReceiveFromChild(child_id, list);
1572 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1573 resource_ids_to_transfer);
1576 // Receive returns back from top-level.
1577 ReturnedResourceArray returned;
1578 TransferableResource::ReturnResources(sent_to_top_level, &returned);
1579 resource_provider_->ReceiveReturnsFromParent(returned);
1580 // Resource is still not yet returned to the child, since it's declared used
1581 // in the parent.
1582 EXPECT_TRUE(returned_to_child.empty());
1583 ASSERT_TRUE(map.find(id) != map.end());
1584 ResourceProvider::ResourceId parent_id = map.find(id)->second;
1585 EXPECT_FALSE(resource_provider_->InUseByConsumer(parent_id));
1588 sent_to_top_level.clear();
1589 // Parent transfers again to top-level.
1590 ASSERT_TRUE(map.find(id) != map.end());
1591 ResourceProvider::ResourceId parent_id = map.find(id)->second;
1592 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1593 resource_ids_to_transfer.push_back(parent_id);
1594 resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1595 &sent_to_top_level);
1596 EXPECT_TRUE(resource_provider_->InUseByConsumer(parent_id));
1599 // Receive returns back from top-level.
1600 ReturnedResourceArray returned;
1601 TransferableResource::ReturnResources(sent_to_top_level, &returned);
1602 resource_provider_->ReceiveReturnsFromParent(returned);
1603 // Resource is still not yet returned to the child, since it's still
1604 // declared used in the parent.
1605 EXPECT_TRUE(returned_to_child.empty());
1606 ASSERT_TRUE(map.find(id) != map.end());
1607 ResourceProvider::ResourceId parent_id = map.find(id)->second;
1608 EXPECT_FALSE(resource_provider_->InUseByConsumer(parent_id));
1611 // Stop using resource.
1612 ResourceProvider::ResourceIdArray empty;
1613 resource_provider_->DeclareUsedResourcesFromChild(child_id, empty);
1614 // Resource should have been returned to the child, since it's no longer in
1615 // use by the top-level.
1616 ASSERT_EQ(1u, returned_to_child.size());
1617 EXPECT_EQ(id, returned_to_child[0].id);
1618 EXPECT_EQ(2, returned_to_child[0].count);
1619 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
1620 returned_to_child.clear();
1621 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id));
1625 class ResourceProviderTestTextureFilters : public ResourceProviderTest {
1626 public:
1627 static void RunTest(GLenum child_filter, GLenum parent_filter) {
1628 scoped_ptr<TextureStateTrackingContext> child_context_owned(
1629 new TextureStateTrackingContext);
1630 TextureStateTrackingContext* child_context = child_context_owned.get();
1632 FakeOutputSurfaceClient child_output_surface_client;
1633 scoped_ptr<OutputSurface> child_output_surface(
1634 FakeOutputSurface::Create3d(child_context_owned.Pass()));
1635 CHECK(child_output_surface->BindToClient(&child_output_surface_client));
1636 scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
1637 new TestSharedBitmapManager());
1639 scoped_ptr<ResourceProvider> child_resource_provider(
1640 ResourceProvider::Create(child_output_surface.get(),
1641 shared_bitmap_manager.get(),
1642 NULL,
1643 NULL,
1645 false,
1646 1));
1648 scoped_ptr<TextureStateTrackingContext> parent_context_owned(
1649 new TextureStateTrackingContext);
1650 TextureStateTrackingContext* parent_context = parent_context_owned.get();
1652 FakeOutputSurfaceClient parent_output_surface_client;
1653 scoped_ptr<OutputSurface> parent_output_surface(
1654 FakeOutputSurface::Create3d(parent_context_owned.Pass()));
1655 CHECK(parent_output_surface->BindToClient(&parent_output_surface_client));
1657 scoped_ptr<ResourceProvider> parent_resource_provider(
1658 ResourceProvider::Create(parent_output_surface.get(),
1659 shared_bitmap_manager.get(),
1660 NULL,
1661 NULL,
1663 false,
1664 1));
1666 gfx::Size size(1, 1);
1667 ResourceFormat format = RGBA_8888;
1668 int child_texture_id = 1;
1669 int parent_texture_id = 2;
1671 size_t pixel_size = TextureSizeBytes(size, format);
1672 ASSERT_EQ(4U, pixel_size);
1674 ResourceProvider::ResourceId id = child_resource_provider->CreateResource(
1675 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
1677 // The new texture is created with GL_LINEAR.
1678 EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, child_texture_id))
1679 .Times(2); // Once to create and once to allocate.
1680 EXPECT_CALL(*child_context,
1681 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
1682 EXPECT_CALL(*child_context,
1683 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
1684 EXPECT_CALL(
1685 *child_context,
1686 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
1687 EXPECT_CALL(
1688 *child_context,
1689 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
1690 EXPECT_CALL(*child_context,
1691 texParameteri(GL_TEXTURE_2D,
1692 GL_TEXTURE_POOL_CHROMIUM,
1693 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM));
1694 child_resource_provider->AllocateForTesting(id);
1695 Mock::VerifyAndClearExpectations(child_context);
1697 uint8_t data[4] = { 1, 2, 3, 4 };
1698 gfx::Rect rect(size);
1700 EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, child_texture_id));
1701 child_resource_provider->SetPixels(id, data, rect, rect, gfx::Vector2d());
1702 Mock::VerifyAndClearExpectations(child_context);
1704 // The texture is set to |child_filter| in the child.
1705 EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, child_texture_id));
1706 if (child_filter != GL_LINEAR) {
1707 EXPECT_CALL(
1708 *child_context,
1709 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, child_filter));
1710 EXPECT_CALL(
1711 *child_context,
1712 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, child_filter));
1714 SetResourceFilter(child_resource_provider.get(), id, child_filter);
1715 Mock::VerifyAndClearExpectations(child_context);
1717 ReturnedResourceArray returned_to_child;
1718 int child_id = parent_resource_provider->CreateChild(
1719 GetReturnCallback(&returned_to_child));
1721 // Transfer some resource to the parent.
1722 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1723 resource_ids_to_transfer.push_back(id);
1724 TransferableResourceArray list;
1726 EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, child_texture_id));
1727 EXPECT_CALL(*child_context,
1728 produceTextureCHROMIUM(GL_TEXTURE_2D, _));
1729 EXPECT_CALL(*child_context, insertSyncPoint());
1730 child_resource_provider->PrepareSendToParent(resource_ids_to_transfer,
1731 &list);
1732 Mock::VerifyAndClearExpectations(child_context);
1734 ASSERT_EQ(1u, list.size());
1735 EXPECT_EQ(static_cast<unsigned>(child_filter), list[0].filter);
1737 EXPECT_CALL(*parent_context,
1738 bindTexture(GL_TEXTURE_2D, parent_texture_id));
1739 EXPECT_CALL(*parent_context, consumeTextureCHROMIUM(GL_TEXTURE_2D, _));
1740 parent_resource_provider->ReceiveFromChild(child_id, list);
1742 parent_resource_provider->WaitSyncPointIfNeeded(list[0].id);
1743 ResourceProvider::ScopedReadLockGL lock(parent_resource_provider.get(),
1744 list[0].id);
1746 Mock::VerifyAndClearExpectations(parent_context);
1748 parent_resource_provider->DeclareUsedResourcesFromChild(
1749 child_id, resource_ids_to_transfer);
1750 Mock::VerifyAndClearExpectations(parent_context);
1752 ResourceProvider::ResourceIdMap resource_map =
1753 parent_resource_provider->GetChildToParentMap(child_id);
1754 ResourceProvider::ResourceId mapped_id = resource_map[id];
1755 EXPECT_NE(0u, mapped_id);
1757 // The texture is set to |parent_filter| in the parent.
1758 EXPECT_CALL(*parent_context, bindTexture(GL_TEXTURE_2D, parent_texture_id));
1759 EXPECT_CALL(
1760 *parent_context,
1761 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, parent_filter));
1762 EXPECT_CALL(
1763 *parent_context,
1764 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, parent_filter));
1765 SetResourceFilter(parent_resource_provider.get(), mapped_id, parent_filter);
1766 Mock::VerifyAndClearExpectations(parent_context);
1768 // The texture should be reset to |child_filter| in the parent when it is
1769 // returned, since that is how it was received.
1770 EXPECT_CALL(*parent_context, bindTexture(GL_TEXTURE_2D, parent_texture_id));
1771 EXPECT_CALL(
1772 *parent_context,
1773 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, child_filter));
1774 EXPECT_CALL(
1775 *parent_context,
1776 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, child_filter));
1779 EXPECT_EQ(0u, returned_to_child.size());
1781 // Transfer resources back from the parent to the child. Set no resources
1782 // as being in use.
1783 ResourceProvider::ResourceIdArray no_resources;
1784 EXPECT_CALL(*parent_context, insertSyncPoint());
1785 parent_resource_provider->DeclareUsedResourcesFromChild(child_id,
1786 no_resources);
1787 Mock::VerifyAndClearExpectations(parent_context);
1789 ASSERT_EQ(1u, returned_to_child.size());
1790 child_resource_provider->ReceiveReturnsFromParent(returned_to_child);
1793 // The child remembers the texture filter is set to |child_filter|.
1794 EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, child_texture_id));
1795 SetResourceFilter(child_resource_provider.get(), id, child_filter);
1796 Mock::VerifyAndClearExpectations(child_context);
1800 TEST_P(ResourceProviderTest, TextureFilters_ChildNearestParentLinear) {
1801 if (GetParam() != ResourceProvider::GLTexture)
1802 return;
1803 ResourceProviderTestTextureFilters::RunTest(GL_NEAREST, GL_LINEAR);
1806 TEST_P(ResourceProviderTest, TextureFilters_ChildLinearParentNearest) {
1807 if (GetParam() != ResourceProvider::GLTexture)
1808 return;
1809 ResourceProviderTestTextureFilters::RunTest(GL_LINEAR, GL_NEAREST);
1812 TEST_P(ResourceProviderTest, TransferMailboxResources) {
1813 // Other mailbox transfers tested elsewhere.
1814 if (GetParam() != ResourceProvider::GLTexture)
1815 return;
1816 unsigned texture = context()->createTexture();
1817 context()->bindTexture(GL_TEXTURE_2D, texture);
1818 uint8_t data[4] = { 1, 2, 3, 4 };
1819 context()->texImage2D(
1820 GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &data);
1821 gpu::Mailbox mailbox;
1822 context()->genMailboxCHROMIUM(mailbox.name);
1823 context()->produceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
1824 uint32 sync_point = context()->insertSyncPoint();
1826 // All the logic below assumes that the sync points are all positive.
1827 EXPECT_LT(0u, sync_point);
1829 uint32 release_sync_point = 0;
1830 bool lost_resource = false;
1831 BlockingTaskRunner* main_thread_task_runner = NULL;
1832 ReleaseCallbackImpl callback = base::Bind(ReleaseCallback,
1833 &release_sync_point,
1834 &lost_resource,
1835 &main_thread_task_runner);
1836 ResourceProvider::ResourceId resource =
1837 resource_provider_->CreateResourceFromTextureMailbox(
1838 TextureMailbox(mailbox, GL_TEXTURE_2D, sync_point),
1839 SingleReleaseCallbackImpl::Create(callback));
1840 EXPECT_EQ(1u, context()->NumTextures());
1841 EXPECT_EQ(0u, release_sync_point);
1843 // Transfer the resource, expect the sync points to be consistent.
1844 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1845 resource_ids_to_transfer.push_back(resource);
1846 TransferableResourceArray list;
1847 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
1848 ASSERT_EQ(1u, list.size());
1849 EXPECT_LE(sync_point, list[0].mailbox_holder.sync_point);
1850 EXPECT_EQ(0,
1851 memcmp(mailbox.name,
1852 list[0].mailbox_holder.mailbox.name,
1853 sizeof(mailbox.name)));
1854 EXPECT_EQ(0u, release_sync_point);
1856 context()->waitSyncPoint(list[0].mailbox_holder.sync_point);
1857 unsigned other_texture = context()->createTexture();
1858 context()->bindTexture(GL_TEXTURE_2D, other_texture);
1859 context()->consumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
1860 uint8_t test_data[4] = { 0 };
1861 context()->GetPixels(
1862 gfx::Size(1, 1), RGBA_8888, test_data);
1863 EXPECT_EQ(0, memcmp(data, test_data, sizeof(data)));
1864 context()->produceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
1865 context()->deleteTexture(other_texture);
1866 list[0].mailbox_holder.sync_point = context()->insertSyncPoint();
1867 EXPECT_LT(0u, list[0].mailbox_holder.sync_point);
1869 // Receive the resource, then delete it, expect the sync points to be
1870 // consistent.
1871 ReturnedResourceArray returned;
1872 TransferableResource::ReturnResources(list, &returned);
1873 resource_provider_->ReceiveReturnsFromParent(returned);
1874 EXPECT_EQ(1u, context()->NumTextures());
1875 EXPECT_EQ(0u, release_sync_point);
1877 resource_provider_->DeleteResource(resource);
1878 EXPECT_LE(list[0].mailbox_holder.sync_point, release_sync_point);
1879 EXPECT_FALSE(lost_resource);
1880 EXPECT_EQ(main_thread_task_runner_.get(), main_thread_task_runner);
1883 // We're going to do the same thing as above, but testing the case where we
1884 // delete the resource before we receive it back.
1885 sync_point = release_sync_point;
1886 EXPECT_LT(0u, sync_point);
1887 release_sync_point = 0;
1888 resource = resource_provider_->CreateResourceFromTextureMailbox(
1889 TextureMailbox(mailbox, GL_TEXTURE_2D, sync_point),
1890 SingleReleaseCallbackImpl::Create(callback));
1891 EXPECT_EQ(1u, context()->NumTextures());
1892 EXPECT_EQ(0u, release_sync_point);
1894 // Transfer the resource, expect the sync points to be consistent.
1895 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1896 resource_ids_to_transfer.push_back(resource);
1897 TransferableResourceArray list;
1898 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
1899 ASSERT_EQ(1u, list.size());
1900 EXPECT_LE(sync_point, list[0].mailbox_holder.sync_point);
1901 EXPECT_EQ(0,
1902 memcmp(mailbox.name,
1903 list[0].mailbox_holder.mailbox.name,
1904 sizeof(mailbox.name)));
1905 EXPECT_EQ(0u, release_sync_point);
1907 context()->waitSyncPoint(list[0].mailbox_holder.sync_point);
1908 unsigned other_texture = context()->createTexture();
1909 context()->bindTexture(GL_TEXTURE_2D, other_texture);
1910 context()->consumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
1911 uint8_t test_data[4] = { 0 };
1912 context()->GetPixels(
1913 gfx::Size(1, 1), RGBA_8888, test_data);
1914 EXPECT_EQ(0, memcmp(data, test_data, sizeof(data)));
1915 context()->produceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
1916 context()->deleteTexture(other_texture);
1917 list[0].mailbox_holder.sync_point = context()->insertSyncPoint();
1918 EXPECT_LT(0u, list[0].mailbox_holder.sync_point);
1920 // Delete the resource, which shouldn't do anything.
1921 resource_provider_->DeleteResource(resource);
1922 EXPECT_EQ(1u, context()->NumTextures());
1923 EXPECT_EQ(0u, release_sync_point);
1925 // Then receive the resource which should release the mailbox, expect the
1926 // sync points to be consistent.
1927 ReturnedResourceArray returned;
1928 TransferableResource::ReturnResources(list, &returned);
1929 resource_provider_->ReceiveReturnsFromParent(returned);
1930 EXPECT_LE(list[0].mailbox_holder.sync_point, release_sync_point);
1931 EXPECT_FALSE(lost_resource);
1932 EXPECT_EQ(main_thread_task_runner_.get(), main_thread_task_runner);
1935 context()->waitSyncPoint(release_sync_point);
1936 context()->bindTexture(GL_TEXTURE_2D, texture);
1937 context()->consumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
1938 context()->deleteTexture(texture);
1941 TEST_P(ResourceProviderTest, LostResourceInParent) {
1942 gfx::Size size(1, 1);
1943 ResourceFormat format = RGBA_8888;
1944 ResourceProvider::ResourceId resource =
1945 child_resource_provider_->CreateResource(
1946 size,
1947 GL_CLAMP_TO_EDGE,
1948 ResourceProvider::TextureHintImmutable,
1949 format);
1950 child_resource_provider_->AllocateForTesting(resource);
1951 // Expect a GL resource to be lost.
1952 bool should_lose_resource = GetParam() == ResourceProvider::GLTexture;
1954 ReturnedResourceArray returned_to_child;
1955 int child_id =
1956 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1958 // Transfer the resource to the parent.
1959 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1960 resource_ids_to_transfer.push_back(resource);
1961 TransferableResourceArray list;
1962 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1963 &list);
1964 EXPECT_EQ(1u, list.size());
1966 resource_provider_->ReceiveFromChild(child_id, list);
1967 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1968 resource_ids_to_transfer);
1971 // Lose the output surface in the parent.
1972 resource_provider_->DidLoseOutputSurface();
1975 EXPECT_EQ(0u, returned_to_child.size());
1977 // Transfer resources back from the parent to the child. Set no resources as
1978 // being in use.
1979 ResourceProvider::ResourceIdArray no_resources;
1980 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
1982 // Expect a GL resource to be lost.
1983 ASSERT_EQ(1u, returned_to_child.size());
1984 EXPECT_EQ(should_lose_resource, returned_to_child[0].lost);
1985 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
1986 returned_to_child.clear();
1989 // A GL resource should be lost.
1990 EXPECT_EQ(should_lose_resource, child_resource_provider_->IsLost(resource));
1992 // Lost resources stay in use in the parent forever.
1993 EXPECT_EQ(should_lose_resource,
1994 child_resource_provider_->InUseByConsumer(resource));
1997 TEST_P(ResourceProviderTest, LostResourceInGrandParent) {
1998 gfx::Size size(1, 1);
1999 ResourceFormat format = RGBA_8888;
2000 ResourceProvider::ResourceId resource =
2001 child_resource_provider_->CreateResource(
2002 size,
2003 GL_CLAMP_TO_EDGE,
2004 ResourceProvider::TextureHintImmutable,
2005 format);
2006 child_resource_provider_->AllocateForTesting(resource);
2008 ReturnedResourceArray returned_to_child;
2009 int child_id =
2010 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
2012 // Transfer the resource to the parent.
2013 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2014 resource_ids_to_transfer.push_back(resource);
2015 TransferableResourceArray list;
2016 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
2017 &list);
2018 EXPECT_EQ(1u, list.size());
2020 resource_provider_->ReceiveFromChild(child_id, list);
2021 resource_provider_->DeclareUsedResourcesFromChild(child_id,
2022 resource_ids_to_transfer);
2026 ResourceProvider::ResourceIdMap resource_map =
2027 resource_provider_->GetChildToParentMap(child_id);
2028 ResourceProvider::ResourceId parent_resource = resource_map[resource];
2029 EXPECT_NE(0u, parent_resource);
2031 // Transfer to a grandparent.
2032 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2033 resource_ids_to_transfer.push_back(parent_resource);
2034 TransferableResourceArray list;
2035 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
2037 // Receive back a lost resource from the grandparent.
2038 EXPECT_EQ(1u, list.size());
2039 EXPECT_EQ(parent_resource, list[0].id);
2040 ReturnedResourceArray returned;
2041 TransferableResource::ReturnResources(list, &returned);
2042 EXPECT_EQ(1u, returned.size());
2043 EXPECT_EQ(parent_resource, returned[0].id);
2044 returned[0].lost = true;
2045 resource_provider_->ReceiveReturnsFromParent(returned);
2047 // The resource should be lost.
2048 EXPECT_TRUE(resource_provider_->IsLost(parent_resource));
2050 // Lost resources stay in use in the parent forever.
2051 EXPECT_TRUE(resource_provider_->InUseByConsumer(parent_resource));
2055 EXPECT_EQ(0u, returned_to_child.size());
2057 // Transfer resources back from the parent to the child. Set no resources as
2058 // being in use.
2059 ResourceProvider::ResourceIdArray no_resources;
2060 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
2062 // Expect the resource to be lost.
2063 ASSERT_EQ(1u, returned_to_child.size());
2064 EXPECT_TRUE(returned_to_child[0].lost);
2065 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
2066 returned_to_child.clear();
2069 // The resource should be lost.
2070 EXPECT_TRUE(child_resource_provider_->IsLost(resource));
2072 // Lost resources stay in use in the parent forever.
2073 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(resource));
2076 TEST_P(ResourceProviderTest, LostMailboxInParent) {
2077 uint32 release_sync_point = 0;
2078 bool lost_resource = false;
2079 bool release_called = false;
2080 uint32 sync_point = 0;
2081 ResourceProvider::ResourceId resource = CreateChildMailbox(
2082 &release_sync_point, &lost_resource, &release_called, &sync_point);
2084 ReturnedResourceArray returned_to_child;
2085 int child_id =
2086 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
2088 // Transfer the resource to the parent.
2089 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2090 resource_ids_to_transfer.push_back(resource);
2091 TransferableResourceArray list;
2092 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
2093 &list);
2094 EXPECT_EQ(1u, list.size());
2096 resource_provider_->ReceiveFromChild(child_id, list);
2097 resource_provider_->DeclareUsedResourcesFromChild(child_id,
2098 resource_ids_to_transfer);
2101 // Lose the output surface in the parent.
2102 resource_provider_->DidLoseOutputSurface();
2105 EXPECT_EQ(0u, returned_to_child.size());
2107 // Transfer resources back from the parent to the child. Set no resources as
2108 // being in use.
2109 ResourceProvider::ResourceIdArray no_resources;
2110 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
2112 ASSERT_EQ(1u, returned_to_child.size());
2113 // Losing an output surface only loses hardware resources.
2114 EXPECT_EQ(returned_to_child[0].lost,
2115 GetParam() == ResourceProvider::GLTexture);
2116 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
2117 returned_to_child.clear();
2120 // Delete the resource in the child. Expect the resource to be lost if it's
2121 // a GL texture.
2122 child_resource_provider_->DeleteResource(resource);
2123 EXPECT_EQ(lost_resource, GetParam() == ResourceProvider::GLTexture);
2126 TEST_P(ResourceProviderTest, LostMailboxInGrandParent) {
2127 uint32 release_sync_point = 0;
2128 bool lost_resource = false;
2129 bool release_called = false;
2130 uint32 sync_point = 0;
2131 ResourceProvider::ResourceId resource = CreateChildMailbox(
2132 &release_sync_point, &lost_resource, &release_called, &sync_point);
2134 ReturnedResourceArray returned_to_child;
2135 int child_id =
2136 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
2138 // Transfer the resource to the parent.
2139 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2140 resource_ids_to_transfer.push_back(resource);
2141 TransferableResourceArray list;
2142 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
2143 &list);
2144 EXPECT_EQ(1u, list.size());
2146 resource_provider_->ReceiveFromChild(child_id, list);
2147 resource_provider_->DeclareUsedResourcesFromChild(child_id,
2148 resource_ids_to_transfer);
2152 ResourceProvider::ResourceIdMap resource_map =
2153 resource_provider_->GetChildToParentMap(child_id);
2154 ResourceProvider::ResourceId parent_resource = resource_map[resource];
2155 EXPECT_NE(0u, parent_resource);
2157 // Transfer to a grandparent.
2158 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2159 resource_ids_to_transfer.push_back(parent_resource);
2160 TransferableResourceArray list;
2161 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
2163 // Receive back a lost resource from the grandparent.
2164 EXPECT_EQ(1u, list.size());
2165 EXPECT_EQ(parent_resource, list[0].id);
2166 ReturnedResourceArray returned;
2167 TransferableResource::ReturnResources(list, &returned);
2168 EXPECT_EQ(1u, returned.size());
2169 EXPECT_EQ(parent_resource, returned[0].id);
2170 returned[0].lost = true;
2171 resource_provider_->ReceiveReturnsFromParent(returned);
2175 EXPECT_EQ(0u, returned_to_child.size());
2177 // Transfer resources back from the parent to the child. Set no resources as
2178 // being in use.
2179 ResourceProvider::ResourceIdArray no_resources;
2180 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
2182 // Expect the resource to be lost.
2183 ASSERT_EQ(1u, returned_to_child.size());
2184 EXPECT_TRUE(returned_to_child[0].lost);
2185 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
2186 returned_to_child.clear();
2189 // Delete the resource in the child. Expect the resource to be lost.
2190 child_resource_provider_->DeleteResource(resource);
2191 EXPECT_TRUE(lost_resource);
2194 TEST_P(ResourceProviderTest, Shutdown) {
2195 uint32 release_sync_point = 0;
2196 bool lost_resource = false;
2197 bool release_called = false;
2198 uint32 sync_point = 0;
2199 CreateChildMailbox(
2200 &release_sync_point, &lost_resource, &release_called, &sync_point);
2202 EXPECT_EQ(0u, release_sync_point);
2203 EXPECT_FALSE(lost_resource);
2205 child_resource_provider_ = nullptr;
2207 if (GetParam() == ResourceProvider::GLTexture) {
2208 EXPECT_LE(sync_point, release_sync_point);
2210 EXPECT_TRUE(release_called);
2211 EXPECT_FALSE(lost_resource);
2214 TEST_P(ResourceProviderTest, ShutdownWithExportedResource) {
2215 uint32 release_sync_point = 0;
2216 bool lost_resource = false;
2217 bool release_called = false;
2218 uint32 sync_point = 0;
2219 ResourceProvider::ResourceId resource = CreateChildMailbox(
2220 &release_sync_point, &lost_resource, &release_called, &sync_point);
2222 // Transfer the resource, so we can't release it properly on shutdown.
2223 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2224 resource_ids_to_transfer.push_back(resource);
2225 TransferableResourceArray list;
2226 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
2227 &list);
2229 EXPECT_EQ(0u, release_sync_point);
2230 EXPECT_FALSE(lost_resource);
2232 child_resource_provider_ = nullptr;
2234 // Since the resource is in the parent, the child considers it lost.
2235 EXPECT_EQ(0u, release_sync_point);
2236 EXPECT_TRUE(lost_resource);
2239 TEST_P(ResourceProviderTest, LostContext) {
2240 // TextureMailbox callbacks only exist for GL textures for now.
2241 if (GetParam() != ResourceProvider::GLTexture)
2242 return;
2243 unsigned texture = context()->createTexture();
2244 context()->bindTexture(GL_TEXTURE_2D, texture);
2245 gpu::Mailbox mailbox;
2246 context()->genMailboxCHROMIUM(mailbox.name);
2247 context()->produceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
2248 uint32 sync_point = context()->insertSyncPoint();
2250 EXPECT_LT(0u, sync_point);
2252 uint32 release_sync_point = 0;
2253 bool lost_resource = false;
2254 BlockingTaskRunner* main_thread_task_runner = NULL;
2255 scoped_ptr<SingleReleaseCallbackImpl> callback =
2256 SingleReleaseCallbackImpl::Create(base::Bind(ReleaseCallback,
2257 &release_sync_point,
2258 &lost_resource,
2259 &main_thread_task_runner));
2260 resource_provider_->CreateResourceFromTextureMailbox(
2261 TextureMailbox(mailbox, GL_TEXTURE_2D, sync_point), callback.Pass());
2263 EXPECT_EQ(0u, release_sync_point);
2264 EXPECT_FALSE(lost_resource);
2265 EXPECT_EQ(NULL, main_thread_task_runner);
2267 resource_provider_->DidLoseOutputSurface();
2268 resource_provider_ = nullptr;
2270 EXPECT_LE(sync_point, release_sync_point);
2271 EXPECT_TRUE(lost_resource);
2272 EXPECT_EQ(main_thread_task_runner_.get(), main_thread_task_runner);
2275 TEST_P(ResourceProviderTest, ScopedSampler) {
2276 // Sampling is only supported for GL textures.
2277 if (GetParam() != ResourceProvider::GLTexture)
2278 return;
2280 scoped_ptr<TextureStateTrackingContext> context_owned(
2281 new TextureStateTrackingContext);
2282 TextureStateTrackingContext* context = context_owned.get();
2284 FakeOutputSurfaceClient output_surface_client;
2285 scoped_ptr<OutputSurface> output_surface(
2286 FakeOutputSurface::Create3d(context_owned.Pass()));
2287 CHECK(output_surface->BindToClient(&output_surface_client));
2289 scoped_ptr<ResourceProvider> resource_provider(
2290 ResourceProvider::Create(output_surface.get(),
2291 shared_bitmap_manager_.get(),
2292 gpu_memory_buffer_manager_.get(),
2293 NULL,
2295 false,
2296 1));
2298 gfx::Size size(1, 1);
2299 ResourceFormat format = RGBA_8888;
2300 int texture_id = 1;
2302 ResourceProvider::ResourceId id = resource_provider->CreateResource(
2303 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
2305 // Check that the texture gets created with the right sampler settings.
2306 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id))
2307 .Times(2); // Once to create and once to allocate.
2308 EXPECT_CALL(*context,
2309 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
2310 EXPECT_CALL(*context,
2311 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
2312 EXPECT_CALL(
2313 *context,
2314 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
2315 EXPECT_CALL(
2316 *context,
2317 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
2318 EXPECT_CALL(*context,
2319 texParameteri(GL_TEXTURE_2D,
2320 GL_TEXTURE_POOL_CHROMIUM,
2321 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM));
2323 resource_provider->AllocateForTesting(id);
2324 Mock::VerifyAndClearExpectations(context);
2326 // Creating a sampler with the default filter should not change any texture
2327 // parameters.
2329 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
2330 ResourceProvider::ScopedSamplerGL sampler(
2331 resource_provider.get(), id, GL_TEXTURE_2D, GL_LINEAR);
2332 Mock::VerifyAndClearExpectations(context);
2335 // Using a different filter should be reflected in the texture parameters.
2337 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
2338 EXPECT_CALL(
2339 *context,
2340 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
2341 EXPECT_CALL(
2342 *context,
2343 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
2344 ResourceProvider::ScopedSamplerGL sampler(
2345 resource_provider.get(), id, GL_TEXTURE_2D, GL_NEAREST);
2346 Mock::VerifyAndClearExpectations(context);
2349 // Test resetting to the default filter.
2351 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
2352 EXPECT_CALL(*context,
2353 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
2354 EXPECT_CALL(*context,
2355 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
2356 ResourceProvider::ScopedSamplerGL sampler(
2357 resource_provider.get(), id, GL_TEXTURE_2D, GL_LINEAR);
2358 Mock::VerifyAndClearExpectations(context);
2362 TEST_P(ResourceProviderTest, ManagedResource) {
2363 // Sampling is only supported for GL textures.
2364 if (GetParam() != ResourceProvider::GLTexture)
2365 return;
2367 scoped_ptr<TextureStateTrackingContext> context_owned(
2368 new TextureStateTrackingContext);
2369 TextureStateTrackingContext* context = context_owned.get();
2371 FakeOutputSurfaceClient output_surface_client;
2372 scoped_ptr<OutputSurface> output_surface(
2373 FakeOutputSurface::Create3d(context_owned.Pass()));
2374 CHECK(output_surface->BindToClient(&output_surface_client));
2376 scoped_ptr<ResourceProvider> resource_provider(
2377 ResourceProvider::Create(output_surface.get(),
2378 shared_bitmap_manager_.get(),
2379 gpu_memory_buffer_manager_.get(),
2380 NULL,
2382 false,
2383 1));
2385 gfx::Size size(1, 1);
2386 ResourceFormat format = RGBA_8888;
2387 int texture_id = 1;
2389 // Check that the texture gets created with the right sampler settings.
2390 ResourceProvider::ResourceId id = resource_provider->CreateManagedResource(
2391 size,
2392 GL_TEXTURE_2D,
2393 GL_CLAMP_TO_EDGE,
2394 ResourceProvider::TextureHintImmutable,
2395 format);
2396 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
2397 EXPECT_CALL(*context,
2398 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
2399 EXPECT_CALL(*context,
2400 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
2401 EXPECT_CALL(
2402 *context,
2403 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
2404 EXPECT_CALL(
2405 *context,
2406 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
2407 EXPECT_CALL(*context,
2408 texParameteri(GL_TEXTURE_2D,
2409 GL_TEXTURE_POOL_CHROMIUM,
2410 GL_TEXTURE_POOL_MANAGED_CHROMIUM));
2411 resource_provider->CreateForTesting(id);
2412 EXPECT_NE(0u, id);
2414 Mock::VerifyAndClearExpectations(context);
2417 TEST_P(ResourceProviderTest, TextureWrapMode) {
2418 // Sampling is only supported for GL textures.
2419 if (GetParam() != ResourceProvider::GLTexture)
2420 return;
2422 scoped_ptr<TextureStateTrackingContext> context_owned(
2423 new TextureStateTrackingContext);
2424 TextureStateTrackingContext* context = context_owned.get();
2426 FakeOutputSurfaceClient output_surface_client;
2427 scoped_ptr<OutputSurface> output_surface(
2428 FakeOutputSurface::Create3d(context_owned.Pass()));
2429 CHECK(output_surface->BindToClient(&output_surface_client));
2431 scoped_ptr<ResourceProvider> resource_provider(
2432 ResourceProvider::Create(output_surface.get(),
2433 shared_bitmap_manager_.get(),
2434 gpu_memory_buffer_manager_.get(),
2435 NULL,
2437 false,
2438 1));
2440 gfx::Size size(1, 1);
2441 ResourceFormat format = RGBA_8888;
2442 GLenum texture_pool = GL_TEXTURE_POOL_UNMANAGED_CHROMIUM;
2444 for (int texture_id = 1; texture_id <= 2; ++texture_id) {
2445 GLint wrap_mode = texture_id == 1 ? GL_CLAMP_TO_EDGE : GL_REPEAT;
2446 // Check that the texture gets created with the right sampler settings.
2447 ResourceProvider::ResourceId id = resource_provider->CreateGLTexture(
2448 size,
2449 GL_TEXTURE_2D,
2450 texture_pool,
2451 wrap_mode,
2452 ResourceProvider::TextureHintImmutable,
2453 format);
2454 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
2455 EXPECT_CALL(*context,
2456 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
2457 EXPECT_CALL(*context,
2458 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
2459 EXPECT_CALL(*context,
2460 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap_mode));
2461 EXPECT_CALL(*context,
2462 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap_mode));
2463 EXPECT_CALL(*context,
2464 texParameteri(GL_TEXTURE_2D,
2465 GL_TEXTURE_POOL_CHROMIUM,
2466 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM));
2467 resource_provider->CreateForTesting(id);
2468 EXPECT_NE(0u, id);
2470 Mock::VerifyAndClearExpectations(context);
2474 TEST_P(ResourceProviderTest, TextureHint) {
2475 // Sampling is only supported for GL textures.
2476 if (GetParam() != ResourceProvider::GLTexture)
2477 return;
2479 scoped_ptr<TextureStateTrackingContext> context_owned(
2480 new TextureStateTrackingContext);
2481 TextureStateTrackingContext* context = context_owned.get();
2482 context->set_support_texture_storage(true);
2483 context->set_support_texture_usage(true);
2485 FakeOutputSurfaceClient output_surface_client;
2486 scoped_ptr<OutputSurface> output_surface(
2487 FakeOutputSurface::Create3d(context_owned.Pass()));
2488 CHECK(output_surface->BindToClient(&output_surface_client));
2490 scoped_ptr<ResourceProvider> resource_provider(
2491 ResourceProvider::Create(output_surface.get(),
2492 shared_bitmap_manager_.get(),
2493 gpu_memory_buffer_manager_.get(),
2494 NULL,
2496 false,
2497 1));
2499 gfx::Size size(1, 1);
2500 ResourceFormat format = RGBA_8888;
2501 GLenum texture_pool = GL_TEXTURE_POOL_UNMANAGED_CHROMIUM;
2503 const ResourceProvider::TextureHint hints[4] = {
2504 ResourceProvider::TextureHintDefault,
2505 ResourceProvider::TextureHintImmutable,
2506 ResourceProvider::TextureHintFramebuffer,
2507 ResourceProvider::TextureHintImmutableFramebuffer,
2509 for (GLuint texture_id = 1; texture_id <= arraysize(hints); ++texture_id) {
2510 // Check that the texture gets created with the right sampler settings.
2511 ResourceProvider::ResourceId id =
2512 resource_provider->CreateGLTexture(size,
2513 GL_TEXTURE_2D,
2514 texture_pool,
2515 GL_CLAMP_TO_EDGE,
2516 hints[texture_id - 1],
2517 format);
2518 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
2519 EXPECT_CALL(*context,
2520 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
2521 EXPECT_CALL(*context,
2522 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
2523 EXPECT_CALL(
2524 *context,
2525 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
2526 EXPECT_CALL(
2527 *context,
2528 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
2529 EXPECT_CALL(*context,
2530 texParameteri(GL_TEXTURE_2D,
2531 GL_TEXTURE_POOL_CHROMIUM,
2532 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM));
2533 // Check only TextureHintFramebuffer set GL_TEXTURE_USAGE_ANGLE.
2534 bool is_framebuffer_hint =
2535 hints[texture_id - 1] & ResourceProvider::TextureHintFramebuffer;
2536 EXPECT_CALL(*context,
2537 texParameteri(GL_TEXTURE_2D,
2538 GL_TEXTURE_USAGE_ANGLE,
2539 GL_FRAMEBUFFER_ATTACHMENT_ANGLE))
2540 .Times(is_framebuffer_hint ? 1 : 0);
2541 resource_provider->CreateForTesting(id);
2542 EXPECT_NE(0u, id);
2544 Mock::VerifyAndClearExpectations(context);
2548 TEST_P(ResourceProviderTest, TextureMailbox_SharedMemory) {
2549 if (GetParam() != ResourceProvider::Bitmap)
2550 return;
2552 gfx::Size size(64, 64);
2553 const uint32_t kBadBeef = 0xbadbeef;
2554 scoped_ptr<SharedBitmap> shared_bitmap(
2555 CreateAndFillSharedBitmap(shared_bitmap_manager_.get(), size, kBadBeef));
2557 FakeOutputSurfaceClient output_surface_client;
2558 scoped_ptr<OutputSurface> output_surface(
2559 FakeOutputSurface::CreateSoftware(make_scoped_ptr(
2560 new SoftwareOutputDevice)));
2561 CHECK(output_surface->BindToClient(&output_surface_client));
2563 scoped_ptr<ResourceProvider> resource_provider(
2564 ResourceProvider::Create(output_surface.get(),
2565 shared_bitmap_manager_.get(),
2566 gpu_memory_buffer_manager_.get(),
2567 main_thread_task_runner_.get(),
2569 false,
2570 1));
2572 uint32 release_sync_point = 0;
2573 bool lost_resource = false;
2574 BlockingTaskRunner* main_thread_task_runner = NULL;
2575 scoped_ptr<SingleReleaseCallbackImpl> callback =
2576 SingleReleaseCallbackImpl::Create(base::Bind(&ReleaseCallback,
2577 &release_sync_point,
2578 &lost_resource,
2579 &main_thread_task_runner));
2580 TextureMailbox mailbox(shared_bitmap.get(), size);
2582 ResourceProvider::ResourceId id =
2583 resource_provider->CreateResourceFromTextureMailbox(
2584 mailbox, callback.Pass());
2585 EXPECT_NE(0u, id);
2588 ResourceProvider::ScopedReadLockSoftware lock(resource_provider.get(), id);
2589 const SkBitmap* sk_bitmap = lock.sk_bitmap();
2590 EXPECT_EQ(sk_bitmap->width(), size.width());
2591 EXPECT_EQ(sk_bitmap->height(), size.height());
2592 EXPECT_EQ(*sk_bitmap->getAddr32(16, 16), kBadBeef);
2595 resource_provider->DeleteResource(id);
2596 EXPECT_EQ(0u, release_sync_point);
2597 EXPECT_FALSE(lost_resource);
2598 EXPECT_EQ(main_thread_task_runner_.get(), main_thread_task_runner);
2601 class ResourceProviderTestTextureMailboxGLFilters
2602 : public ResourceProviderTest {
2603 public:
2604 static void RunTest(TestSharedBitmapManager* shared_bitmap_manager,
2605 TestGpuMemoryBufferManager* gpu_memory_buffer_manager,
2606 BlockingTaskRunner* main_thread_task_runner,
2607 bool mailbox_nearest_neighbor,
2608 GLenum sampler_filter) {
2609 scoped_ptr<TextureStateTrackingContext> context_owned(
2610 new TextureStateTrackingContext);
2611 TextureStateTrackingContext* context = context_owned.get();
2613 FakeOutputSurfaceClient output_surface_client;
2614 scoped_ptr<OutputSurface> output_surface(
2615 FakeOutputSurface::Create3d(context_owned.Pass()));
2616 CHECK(output_surface->BindToClient(&output_surface_client));
2618 scoped_ptr<ResourceProvider> resource_provider(
2619 ResourceProvider::Create(output_surface.get(),
2620 shared_bitmap_manager,
2621 gpu_memory_buffer_manager,
2622 main_thread_task_runner,
2624 false,
2625 1));
2627 unsigned texture_id = 1;
2628 uint32 sync_point = 30;
2629 unsigned target = GL_TEXTURE_2D;
2631 EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
2632 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
2633 EXPECT_CALL(*context, insertSyncPoint()).Times(0);
2634 EXPECT_CALL(*context, produceTextureCHROMIUM(_, _)).Times(0);
2635 EXPECT_CALL(*context, consumeTextureCHROMIUM(_, _)).Times(0);
2637 gpu::Mailbox gpu_mailbox;
2638 memcpy(gpu_mailbox.name, "Hello world", strlen("Hello world") + 1);
2639 uint32 release_sync_point = 0;
2640 bool lost_resource = false;
2641 BlockingTaskRunner* mailbox_task_runner = NULL;
2642 scoped_ptr<SingleReleaseCallbackImpl> callback =
2643 SingleReleaseCallbackImpl::Create(base::Bind(&ReleaseCallback,
2644 &release_sync_point,
2645 &lost_resource,
2646 &mailbox_task_runner));
2648 TextureMailbox mailbox(gpu_mailbox, target, sync_point);
2649 mailbox.set_nearest_neighbor(mailbox_nearest_neighbor);
2651 ResourceProvider::ResourceId id =
2652 resource_provider->CreateResourceFromTextureMailbox(mailbox,
2653 callback.Pass());
2654 EXPECT_NE(0u, id);
2656 Mock::VerifyAndClearExpectations(context);
2659 // Mailbox sync point WaitSyncPoint before using the texture.
2660 EXPECT_CALL(*context, waitSyncPoint(sync_point));
2661 resource_provider->WaitSyncPointIfNeeded(id);
2662 Mock::VerifyAndClearExpectations(context);
2664 // Using the texture does a consume of the mailbox.
2665 EXPECT_CALL(*context, bindTexture(target, texture_id)).Times(2);
2666 EXPECT_CALL(*context, consumeTextureCHROMIUM(target, _));
2668 EXPECT_CALL(*context, insertSyncPoint()).Times(0);
2669 EXPECT_CALL(*context, produceTextureCHROMIUM(_, _)).Times(0);
2671 // The sampler will reset these if |mailbox_nearest_neighbor| does not
2672 // match |sampler_filter|.
2673 if (mailbox_nearest_neighbor != (sampler_filter == GL_NEAREST)) {
2674 EXPECT_CALL(*context, texParameteri(
2675 GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, sampler_filter));
2676 EXPECT_CALL(*context, texParameteri(
2677 GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, sampler_filter));
2680 ResourceProvider::ScopedSamplerGL lock(
2681 resource_provider.get(), id, sampler_filter);
2682 Mock::VerifyAndClearExpectations(context);
2684 // When done with it, a sync point should be inserted, but no produce is
2685 // necessary.
2686 EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
2687 EXPECT_CALL(*context, insertSyncPoint());
2688 EXPECT_CALL(*context, produceTextureCHROMIUM(_, _)).Times(0);
2690 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
2691 EXPECT_CALL(*context, consumeTextureCHROMIUM(_, _)).Times(0);
2694 resource_provider->DeleteResource(id);
2695 EXPECT_EQ(0u, release_sync_point);
2696 EXPECT_FALSE(lost_resource);
2697 EXPECT_EQ(main_thread_task_runner, mailbox_task_runner);
2701 TEST_P(ResourceProviderTest, TextureMailbox_GLTexture2D_LinearToLinear) {
2702 // Mailboxing is only supported for GL textures.
2703 if (GetParam() != ResourceProvider::GLTexture)
2704 return;
2706 ResourceProviderTestTextureMailboxGLFilters::RunTest(
2707 shared_bitmap_manager_.get(),
2708 gpu_memory_buffer_manager_.get(),
2709 main_thread_task_runner_.get(),
2710 false,
2711 GL_LINEAR);
2714 TEST_P(ResourceProviderTest, TextureMailbox_GLTexture2D_NearestToNearest) {
2715 // Mailboxing is only supported for GL textures.
2716 if (GetParam() != ResourceProvider::GLTexture)
2717 return;
2719 ResourceProviderTestTextureMailboxGLFilters::RunTest(
2720 shared_bitmap_manager_.get(),
2721 gpu_memory_buffer_manager_.get(),
2722 main_thread_task_runner_.get(),
2723 true,
2724 GL_NEAREST);
2727 TEST_P(ResourceProviderTest, TextureMailbox_GLTexture2D_NearestToLinear) {
2728 // Mailboxing is only supported for GL textures.
2729 if (GetParam() != ResourceProvider::GLTexture)
2730 return;
2732 ResourceProviderTestTextureMailboxGLFilters::RunTest(
2733 shared_bitmap_manager_.get(),
2734 gpu_memory_buffer_manager_.get(),
2735 main_thread_task_runner_.get(),
2736 true,
2737 GL_LINEAR);
2740 TEST_P(ResourceProviderTest, TextureMailbox_GLTexture2D_LinearToNearest) {
2741 // Mailboxing is only supported for GL textures.
2742 if (GetParam() != ResourceProvider::GLTexture)
2743 return;
2745 ResourceProviderTestTextureMailboxGLFilters::RunTest(
2746 shared_bitmap_manager_.get(),
2747 gpu_memory_buffer_manager_.get(),
2748 main_thread_task_runner_.get(),
2749 false,
2750 GL_NEAREST);
2753 TEST_P(ResourceProviderTest, TextureMailbox_GLTextureExternalOES) {
2754 // Mailboxing is only supported for GL textures.
2755 if (GetParam() != ResourceProvider::GLTexture)
2756 return;
2758 scoped_ptr<TextureStateTrackingContext> context_owned(
2759 new TextureStateTrackingContext);
2760 TextureStateTrackingContext* context = context_owned.get();
2762 FakeOutputSurfaceClient output_surface_client;
2763 scoped_ptr<OutputSurface> output_surface(
2764 FakeOutputSurface::Create3d(context_owned.Pass()));
2765 CHECK(output_surface->BindToClient(&output_surface_client));
2767 scoped_ptr<ResourceProvider> resource_provider(
2768 ResourceProvider::Create(output_surface.get(),
2769 shared_bitmap_manager_.get(),
2770 gpu_memory_buffer_manager_.get(),
2771 NULL,
2773 false,
2774 1));
2776 unsigned texture_id = 1;
2777 uint32 sync_point = 30;
2778 unsigned target = GL_TEXTURE_EXTERNAL_OES;
2780 EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
2781 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
2782 EXPECT_CALL(*context, insertSyncPoint()).Times(0);
2783 EXPECT_CALL(*context, produceTextureCHROMIUM(_, _)).Times(0);
2784 EXPECT_CALL(*context, consumeTextureCHROMIUM(_, _)).Times(0);
2786 gpu::Mailbox gpu_mailbox;
2787 memcpy(gpu_mailbox.name, "Hello world", strlen("Hello world") + 1);
2788 scoped_ptr<SingleReleaseCallbackImpl> callback =
2789 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback));
2791 TextureMailbox mailbox(gpu_mailbox, target, sync_point);
2793 ResourceProvider::ResourceId id =
2794 resource_provider->CreateResourceFromTextureMailbox(
2795 mailbox, callback.Pass());
2796 EXPECT_NE(0u, id);
2798 Mock::VerifyAndClearExpectations(context);
2801 // Mailbox sync point WaitSyncPoint before using the texture.
2802 EXPECT_CALL(*context, waitSyncPoint(sync_point));
2803 resource_provider->WaitSyncPointIfNeeded(id);
2804 Mock::VerifyAndClearExpectations(context);
2806 // Using the texture does a consume of the mailbox.
2807 EXPECT_CALL(*context, bindTexture(target, texture_id));
2808 EXPECT_CALL(*context, consumeTextureCHROMIUM(target, _));
2810 EXPECT_CALL(*context, insertSyncPoint()).Times(0);
2811 EXPECT_CALL(*context, produceTextureCHROMIUM(_, _)).Times(0);
2813 ResourceProvider::ScopedReadLockGL lock(resource_provider.get(), id);
2814 Mock::VerifyAndClearExpectations(context);
2816 // When done with it, a sync point should be inserted, but no produce is
2817 // necessary.
2818 EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
2819 EXPECT_CALL(*context, insertSyncPoint());
2820 EXPECT_CALL(*context, produceTextureCHROMIUM(_, _)).Times(0);
2822 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
2823 EXPECT_CALL(*context, consumeTextureCHROMIUM(_, _)).Times(0);
2827 TEST_P(ResourceProviderTest,
2828 TextureMailbox_WaitSyncPointIfNeeded_WithSyncPoint) {
2829 // Mailboxing is only supported for GL textures.
2830 if (GetParam() != ResourceProvider::GLTexture)
2831 return;
2833 scoped_ptr<TextureStateTrackingContext> context_owned(
2834 new TextureStateTrackingContext);
2835 TextureStateTrackingContext* context = context_owned.get();
2837 FakeOutputSurfaceClient output_surface_client;
2838 scoped_ptr<OutputSurface> output_surface(
2839 FakeOutputSurface::Create3d(context_owned.Pass()));
2840 CHECK(output_surface->BindToClient(&output_surface_client));
2842 scoped_ptr<ResourceProvider> resource_provider(
2843 ResourceProvider::Create(output_surface.get(),
2844 shared_bitmap_manager_.get(),
2845 gpu_memory_buffer_manager_.get(),
2846 NULL,
2848 false,
2849 1));
2851 uint32 sync_point = 30;
2852 unsigned target = GL_TEXTURE_2D;
2854 EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
2855 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
2856 EXPECT_CALL(*context, insertSyncPoint()).Times(0);
2857 EXPECT_CALL(*context, produceTextureCHROMIUM(_, _)).Times(0);
2858 EXPECT_CALL(*context, consumeTextureCHROMIUM(_, _)).Times(0);
2860 gpu::Mailbox gpu_mailbox;
2861 memcpy(gpu_mailbox.name, "Hello world", strlen("Hello world") + 1);
2862 scoped_ptr<SingleReleaseCallbackImpl> callback =
2863 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback));
2865 TextureMailbox mailbox(gpu_mailbox, target, sync_point);
2867 ResourceProvider::ResourceId id =
2868 resource_provider->CreateResourceFromTextureMailbox(mailbox,
2869 callback.Pass());
2870 EXPECT_NE(0u, id);
2872 Mock::VerifyAndClearExpectations(context);
2875 // First call to WaitSyncPointIfNeeded should call waitSyncPoint.
2876 EXPECT_CALL(*context, waitSyncPoint(sync_point));
2877 resource_provider->WaitSyncPointIfNeeded(id);
2878 Mock::VerifyAndClearExpectations(context);
2880 // Subsequent calls to WaitSyncPointIfNeeded shouldn't call waitSyncPoint.
2881 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
2882 resource_provider->WaitSyncPointIfNeeded(id);
2883 Mock::VerifyAndClearExpectations(context);
2887 TEST_P(ResourceProviderTest, TextureMailbox_WaitSyncPointIfNeeded_NoSyncPoint) {
2888 // Mailboxing is only supported for GL textures.
2889 if (GetParam() != ResourceProvider::GLTexture)
2890 return;
2892 scoped_ptr<TextureStateTrackingContext> context_owned(
2893 new TextureStateTrackingContext);
2894 TextureStateTrackingContext* context = context_owned.get();
2896 FakeOutputSurfaceClient output_surface_client;
2897 scoped_ptr<OutputSurface> output_surface(
2898 FakeOutputSurface::Create3d(context_owned.Pass()));
2899 CHECK(output_surface->BindToClient(&output_surface_client));
2901 scoped_ptr<ResourceProvider> resource_provider(
2902 ResourceProvider::Create(output_surface.get(),
2903 shared_bitmap_manager_.get(),
2904 gpu_memory_buffer_manager_.get(),
2905 NULL,
2907 false,
2908 1));
2910 uint32 sync_point = 0;
2911 unsigned target = GL_TEXTURE_2D;
2913 EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
2914 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
2915 EXPECT_CALL(*context, insertSyncPoint()).Times(0);
2916 EXPECT_CALL(*context, produceTextureCHROMIUM(_, _)).Times(0);
2917 EXPECT_CALL(*context, consumeTextureCHROMIUM(_, _)).Times(0);
2919 gpu::Mailbox gpu_mailbox;
2920 memcpy(gpu_mailbox.name, "Hello world", strlen("Hello world") + 1);
2921 scoped_ptr<SingleReleaseCallbackImpl> callback =
2922 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback));
2924 TextureMailbox mailbox(gpu_mailbox, target, sync_point);
2926 ResourceProvider::ResourceId id =
2927 resource_provider->CreateResourceFromTextureMailbox(mailbox,
2928 callback.Pass());
2929 EXPECT_NE(0u, id);
2931 Mock::VerifyAndClearExpectations(context);
2934 // WaitSyncPointIfNeeded with sync_point == 0 shouldn't call waitSyncPoint.
2935 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
2936 resource_provider->WaitSyncPointIfNeeded(id);
2937 Mock::VerifyAndClearExpectations(context);
2941 class AllocationTrackingContext3D : public TestWebGraphicsContext3D {
2942 public:
2943 MOCK_METHOD0(NextTextureId, GLuint());
2944 MOCK_METHOD1(RetireTextureId, void(GLuint id));
2945 MOCK_METHOD2(bindTexture, void(GLenum target, GLuint texture));
2946 MOCK_METHOD5(texStorage2DEXT,
2947 void(GLenum target,
2948 GLint levels,
2949 GLuint internalformat,
2950 GLint width,
2951 GLint height));
2952 MOCK_METHOD9(texImage2D,
2953 void(GLenum target,
2954 GLint level,
2955 GLenum internalformat,
2956 GLsizei width,
2957 GLsizei height,
2958 GLint border,
2959 GLenum format,
2960 GLenum type,
2961 const void* pixels));
2962 MOCK_METHOD9(texSubImage2D,
2963 void(GLenum target,
2964 GLint level,
2965 GLint xoffset,
2966 GLint yoffset,
2967 GLsizei width,
2968 GLsizei height,
2969 GLenum format,
2970 GLenum type,
2971 const void* pixels));
2972 MOCK_METHOD9(asyncTexImage2DCHROMIUM,
2973 void(GLenum target,
2974 GLint level,
2975 GLenum internalformat,
2976 GLsizei width,
2977 GLsizei height,
2978 GLint border,
2979 GLenum format,
2980 GLenum type,
2981 const void* pixels));
2982 MOCK_METHOD9(asyncTexSubImage2DCHROMIUM,
2983 void(GLenum target,
2984 GLint level,
2985 GLint xoffset,
2986 GLint yoffset,
2987 GLsizei width,
2988 GLsizei height,
2989 GLenum format,
2990 GLenum type,
2991 const void* pixels));
2992 MOCK_METHOD8(compressedTexImage2D,
2993 void(GLenum target,
2994 GLint level,
2995 GLenum internalformat,
2996 GLsizei width,
2997 GLsizei height,
2998 GLint border,
2999 GLsizei image_size,
3000 const void* data));
3001 MOCK_METHOD1(waitAsyncTexImage2DCHROMIUM, void(GLenum));
3002 MOCK_METHOD4(createImageCHROMIUM,
3003 GLuint(ClientBuffer, GLsizei, GLsizei, GLenum));
3004 MOCK_METHOD1(destroyImageCHROMIUM, void(GLuint));
3005 MOCK_METHOD2(bindTexImage2DCHROMIUM, void(GLenum, GLint));
3006 MOCK_METHOD2(releaseTexImage2DCHROMIUM, void(GLenum, GLint));
3008 // We're mocking bindTexture, so we override
3009 // TestWebGraphicsContext3D::texParameteri to avoid assertions related to the
3010 // currently bound texture.
3011 virtual void texParameteri(GLenum target, GLenum pname, GLint param) {}
3014 TEST_P(ResourceProviderTest, TextureAllocation) {
3015 // Only for GL textures.
3016 if (GetParam() != ResourceProvider::GLTexture)
3017 return;
3018 scoped_ptr<AllocationTrackingContext3D> context_owned(
3019 new StrictMock<AllocationTrackingContext3D>);
3020 AllocationTrackingContext3D* context = context_owned.get();
3022 FakeOutputSurfaceClient output_surface_client;
3023 scoped_ptr<OutputSurface> output_surface(
3024 FakeOutputSurface::Create3d(context_owned.Pass()));
3025 CHECK(output_surface->BindToClient(&output_surface_client));
3027 scoped_ptr<ResourceProvider> resource_provider(
3028 ResourceProvider::Create(output_surface.get(),
3029 shared_bitmap_manager_.get(),
3030 gpu_memory_buffer_manager_.get(),
3031 NULL,
3033 false,
3034 1));
3036 gfx::Size size(2, 2);
3037 gfx::Vector2d offset(0, 0);
3038 gfx::Rect rect(0, 0, 2, 2);
3039 ResourceFormat format = RGBA_8888;
3040 ResourceProvider::ResourceId id = 0;
3041 uint8_t pixels[16] = { 0 };
3042 int texture_id = 123;
3044 // Lazy allocation. Don't allocate when creating the resource.
3045 id = resource_provider->CreateResource(
3046 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
3048 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3049 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(1);
3050 resource_provider->CreateForTesting(id);
3052 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3053 resource_provider->DeleteResource(id);
3055 Mock::VerifyAndClearExpectations(context);
3057 // Do allocate when we set the pixels.
3058 id = resource_provider->CreateResource(
3059 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
3061 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3062 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(3);
3063 EXPECT_CALL(*context, texImage2D(_, _, _, 2, 2, _, _, _, _)).Times(1);
3064 EXPECT_CALL(*context, texSubImage2D(_, _, _, _, 2, 2, _, _, _)).Times(1);
3065 resource_provider->SetPixels(id, pixels, rect, rect, offset);
3067 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3068 resource_provider->DeleteResource(id);
3070 Mock::VerifyAndClearExpectations(context);
3072 // Same for async version.
3073 id = resource_provider->CreateResource(
3074 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
3075 resource_provider->AcquirePixelBuffer(id);
3077 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3078 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
3079 EXPECT_CALL(*context, asyncTexImage2DCHROMIUM(_, _, _, 2, 2, _, _, _, _))
3080 .Times(1);
3081 resource_provider->BeginSetPixels(id);
3082 ASSERT_TRUE(resource_provider->DidSetPixelsComplete(id));
3084 resource_provider->ReleasePixelBuffer(id);
3086 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3087 resource_provider->DeleteResource(id);
3089 Mock::VerifyAndClearExpectations(context);
3092 TEST_P(ResourceProviderTest, TextureAllocationHint) {
3093 // Only for GL textures.
3094 if (GetParam() != ResourceProvider::GLTexture)
3095 return;
3096 scoped_ptr<AllocationTrackingContext3D> context_owned(
3097 new StrictMock<AllocationTrackingContext3D>);
3098 AllocationTrackingContext3D* context = context_owned.get();
3099 context->set_support_texture_storage(true);
3100 context->set_support_texture_usage(true);
3102 FakeOutputSurfaceClient output_surface_client;
3103 scoped_ptr<OutputSurface> output_surface(
3104 FakeOutputSurface::Create3d(context_owned.Pass()));
3105 CHECK(output_surface->BindToClient(&output_surface_client));
3107 scoped_ptr<ResourceProvider> resource_provider(
3108 ResourceProvider::Create(output_surface.get(),
3109 shared_bitmap_manager_.get(),
3110 gpu_memory_buffer_manager_.get(),
3111 NULL,
3113 false,
3114 1));
3116 gfx::Size size(2, 2);
3118 const ResourceFormat formats[2] = {RGBA_8888, BGRA_8888};
3119 const ResourceProvider::TextureHint hints[4] = {
3120 ResourceProvider::TextureHintDefault,
3121 ResourceProvider::TextureHintImmutable,
3122 ResourceProvider::TextureHintFramebuffer,
3123 ResourceProvider::TextureHintImmutableFramebuffer,
3125 for (size_t i = 0; i < arraysize(formats); ++i) {
3126 for (GLuint texture_id = 1; texture_id <= arraysize(hints); ++texture_id) {
3127 // Lazy allocation. Don't allocate when creating the resource.
3128 ResourceProvider::ResourceId id = resource_provider->CreateResource(
3129 size, GL_CLAMP_TO_EDGE, hints[texture_id - 1], formats[i]);
3131 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3132 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
3133 bool is_immutable_hint =
3134 hints[texture_id - 1] & ResourceProvider::TextureHintImmutable;
3135 bool support_immutable_texture =
3136 is_immutable_hint && formats[i] == RGBA_8888;
3137 EXPECT_CALL(*context, texStorage2DEXT(_, _, _, 2, 2))
3138 .Times(support_immutable_texture ? 1 : 0);
3139 EXPECT_CALL(*context, texImage2D(_, _, _, 2, 2, _, _, _, _))
3140 .Times(support_immutable_texture ? 0 : 1);
3141 resource_provider->AllocateForTesting(id);
3143 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3144 resource_provider->DeleteResource(id);
3146 Mock::VerifyAndClearExpectations(context);
3151 TEST_P(ResourceProviderTest, TextureAllocationHint_BGRA) {
3152 // Only for GL textures.
3153 if (GetParam() != ResourceProvider::GLTexture)
3154 return;
3155 scoped_ptr<AllocationTrackingContext3D> context_owned(
3156 new StrictMock<AllocationTrackingContext3D>);
3157 AllocationTrackingContext3D* context = context_owned.get();
3158 context->set_support_texture_format_bgra8888(true);
3159 context->set_support_texture_storage(true);
3160 context->set_support_texture_usage(true);
3162 FakeOutputSurfaceClient output_surface_client;
3163 scoped_ptr<OutputSurface> output_surface(
3164 FakeOutputSurface::Create3d(context_owned.Pass()));
3165 CHECK(output_surface->BindToClient(&output_surface_client));
3167 scoped_ptr<ResourceProvider> resource_provider(
3168 ResourceProvider::Create(output_surface.get(),
3169 shared_bitmap_manager_.get(),
3170 gpu_memory_buffer_manager_.get(),
3171 NULL,
3173 false,
3174 1));
3176 gfx::Size size(2, 2);
3177 const ResourceFormat formats[2] = {RGBA_8888, BGRA_8888};
3179 const ResourceProvider::TextureHint hints[4] = {
3180 ResourceProvider::TextureHintDefault,
3181 ResourceProvider::TextureHintImmutable,
3182 ResourceProvider::TextureHintFramebuffer,
3183 ResourceProvider::TextureHintImmutableFramebuffer,
3185 for (size_t i = 0; i < arraysize(formats); ++i) {
3186 for (GLuint texture_id = 1; texture_id <= arraysize(hints); ++texture_id) {
3187 // Lazy allocation. Don't allocate when creating the resource.
3188 ResourceProvider::ResourceId id = resource_provider->CreateResource(
3189 size, GL_CLAMP_TO_EDGE, hints[texture_id - 1], formats[i]);
3191 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3192 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
3193 bool is_immutable_hint =
3194 hints[texture_id - 1] & ResourceProvider::TextureHintImmutable;
3195 EXPECT_CALL(*context, texStorage2DEXT(_, _, _, 2, 2))
3196 .Times(is_immutable_hint ? 1 : 0);
3197 EXPECT_CALL(*context, texImage2D(_, _, _, 2, 2, _, _, _, _))
3198 .Times(is_immutable_hint ? 0 : 1);
3199 resource_provider->AllocateForTesting(id);
3201 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3202 resource_provider->DeleteResource(id);
3204 Mock::VerifyAndClearExpectations(context);
3209 TEST_P(ResourceProviderTest, PixelBuffer_GLTexture) {
3210 if (GetParam() != ResourceProvider::GLTexture)
3211 return;
3212 scoped_ptr<AllocationTrackingContext3D> context_owned(
3213 new StrictMock<AllocationTrackingContext3D>);
3214 AllocationTrackingContext3D* context = context_owned.get();
3216 FakeOutputSurfaceClient output_surface_client;
3217 scoped_ptr<OutputSurface> output_surface(
3218 FakeOutputSurface::Create3d(context_owned.Pass()));
3219 CHECK(output_surface->BindToClient(&output_surface_client));
3221 gfx::Size size(2, 2);
3222 ResourceFormat format = RGBA_8888;
3223 ResourceProvider::ResourceId id = 0;
3224 int texture_id = 123;
3226 scoped_ptr<ResourceProvider> resource_provider(
3227 ResourceProvider::Create(output_surface.get(),
3228 shared_bitmap_manager_.get(),
3229 gpu_memory_buffer_manager_.get(),
3230 NULL,
3232 false,
3233 1));
3235 id = resource_provider->CreateResource(
3236 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
3237 resource_provider->AcquirePixelBuffer(id);
3239 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3240 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
3241 EXPECT_CALL(*context, asyncTexImage2DCHROMIUM(_, _, _, 2, 2, _, _, _, _))
3242 .Times(1);
3243 resource_provider->BeginSetPixels(id);
3245 EXPECT_TRUE(resource_provider->DidSetPixelsComplete(id));
3247 resource_provider->ReleasePixelBuffer(id);
3249 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3250 resource_provider->DeleteResource(id);
3252 Mock::VerifyAndClearExpectations(context);
3255 TEST_P(ResourceProviderTest, ForcingAsyncUploadToComplete) {
3256 // Only for GL textures.
3257 if (GetParam() != ResourceProvider::GLTexture)
3258 return;
3259 scoped_ptr<AllocationTrackingContext3D> context_owned(
3260 new StrictMock<AllocationTrackingContext3D>);
3261 AllocationTrackingContext3D* context = context_owned.get();
3263 FakeOutputSurfaceClient output_surface_client;
3264 scoped_ptr<OutputSurface> output_surface(
3265 FakeOutputSurface::Create3d(context_owned.Pass()));
3266 CHECK(output_surface->BindToClient(&output_surface_client));
3268 gfx::Size size(2, 2);
3269 ResourceFormat format = RGBA_8888;
3270 ResourceProvider::ResourceId id = 0;
3271 int texture_id = 123;
3273 scoped_ptr<ResourceProvider> resource_provider(
3274 ResourceProvider::Create(output_surface.get(),
3275 shared_bitmap_manager_.get(),
3276 gpu_memory_buffer_manager_.get(),
3277 NULL,
3279 false,
3280 1));
3282 id = resource_provider->CreateResource(
3283 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
3284 resource_provider->AcquirePixelBuffer(id);
3286 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3287 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
3288 EXPECT_CALL(*context, asyncTexImage2DCHROMIUM(_, _, _, 2, 2, _, _, _, _))
3289 .Times(1);
3290 resource_provider->BeginSetPixels(id);
3292 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(1);
3293 EXPECT_CALL(*context, waitAsyncTexImage2DCHROMIUM(GL_TEXTURE_2D)).Times(1);
3294 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, 0)).Times(1);
3295 resource_provider->ForceSetPixelsToComplete(id);
3297 resource_provider->ReleasePixelBuffer(id);
3299 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3300 resource_provider->DeleteResource(id);
3302 Mock::VerifyAndClearExpectations(context);
3305 TEST_P(ResourceProviderTest, PixelBufferLostContext) {
3306 scoped_ptr<AllocationTrackingContext3D> context_owned(
3307 new NiceMock<AllocationTrackingContext3D>);
3308 AllocationTrackingContext3D* context = context_owned.get();
3310 FakeOutputSurfaceClient output_surface_client;
3311 scoped_ptr<OutputSurface> output_surface(
3312 FakeOutputSurface::Create3d(context_owned.Pass()));
3313 CHECK(output_surface->BindToClient(&output_surface_client));
3315 gfx::Size size(2, 2);
3316 ResourceFormat format = RGBA_8888;
3317 ResourceProvider::ResourceId id = 0;
3318 int texture_id = 123;
3320 scoped_ptr<ResourceProvider> resource_provider(
3321 ResourceProvider::Create(output_surface.get(),
3322 shared_bitmap_manager_.get(),
3323 gpu_memory_buffer_manager_.get(),
3324 NULL,
3326 false,
3327 1));
3329 EXPECT_CALL(*context, NextTextureId()).WillRepeatedly(Return(texture_id));
3331 id = resource_provider->CreateResource(
3332 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
3333 context->loseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB,
3334 GL_INNOCENT_CONTEXT_RESET_ARB);
3336 resource_provider->AcquirePixelBuffer(id);
3337 int stride;
3338 void* buffer = resource_provider->MapPixelBuffer(id, &stride);
3339 EXPECT_FALSE(buffer);
3340 resource_provider->UnmapPixelBuffer(id);
3341 Mock::VerifyAndClearExpectations(context);
3344 TEST_P(ResourceProviderTest, Image_GLTexture) {
3345 // Only for GL textures.
3346 if (GetParam() != ResourceProvider::GLTexture)
3347 return;
3348 scoped_ptr<AllocationTrackingContext3D> context_owned(
3349 new StrictMock<AllocationTrackingContext3D>);
3350 AllocationTrackingContext3D* context = context_owned.get();
3352 FakeOutputSurfaceClient output_surface_client;
3353 scoped_ptr<OutputSurface> output_surface(
3354 FakeOutputSurface::Create3d(context_owned.Pass()));
3355 CHECK(output_surface->BindToClient(&output_surface_client));
3357 const int kWidth = 2;
3358 const int kHeight = 2;
3359 gfx::Size size(kWidth, kHeight);
3360 ResourceFormat format = RGBA_8888;
3361 ResourceProvider::ResourceId id = 0;
3362 const unsigned kTextureId = 123u;
3363 const unsigned kImageId = 234u;
3365 scoped_ptr<ResourceProvider> resource_provider(
3366 ResourceProvider::Create(output_surface.get(),
3367 shared_bitmap_manager_.get(),
3368 gpu_memory_buffer_manager_.get(),
3369 NULL,
3371 false,
3372 1));
3374 id = resource_provider->CreateResource(
3375 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
3377 EXPECT_CALL(*context, createImageCHROMIUM(_, kWidth, kHeight, GL_RGBA))
3378 .WillOnce(Return(kImageId))
3379 .RetiresOnSaturation();
3381 ResourceProvider::ScopedWriteLockGpuMemoryBuffer lock(
3382 resource_provider.get(), id);
3383 EXPECT_TRUE(!!lock.GetGpuMemoryBuffer());
3386 EXPECT_CALL(*context, NextTextureId())
3387 .WillOnce(Return(kTextureId))
3388 .RetiresOnSaturation();
3389 // Once in CreateTextureId and once in BindForSampling
3390 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kTextureId)).Times(2)
3391 .RetiresOnSaturation();
3392 EXPECT_CALL(*context, bindTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId))
3393 .Times(1)
3394 .RetiresOnSaturation();
3396 ResourceProvider::ScopedSamplerGL lock_gl(
3397 resource_provider.get(), id, GL_TEXTURE_2D, GL_LINEAR);
3398 EXPECT_EQ(kTextureId, lock_gl.texture_id());
3402 ResourceProvider::ScopedWriteLockGpuMemoryBuffer lock(
3403 resource_provider.get(), id);
3404 EXPECT_TRUE(!!lock.GetGpuMemoryBuffer());
3407 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kTextureId)).Times(1)
3408 .RetiresOnSaturation();
3409 EXPECT_CALL(*context, releaseTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId))
3410 .Times(1)
3411 .RetiresOnSaturation();
3412 EXPECT_CALL(*context, bindTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId))
3413 .Times(1)
3414 .RetiresOnSaturation();
3415 EXPECT_CALL(*context, RetireTextureId(kTextureId))
3416 .Times(1)
3417 .RetiresOnSaturation();
3419 ResourceProvider::ScopedSamplerGL lock_gl(
3420 resource_provider.get(), id, GL_TEXTURE_2D, GL_LINEAR);
3421 EXPECT_EQ(kTextureId, lock_gl.texture_id());
3424 EXPECT_CALL(*context, destroyImageCHROMIUM(kImageId))
3425 .Times(1)
3426 .RetiresOnSaturation();
3429 TEST_P(ResourceProviderTest, CopyResource_GLTexture) {
3430 if (GetParam() != ResourceProvider::GLTexture)
3431 return;
3432 scoped_ptr<AllocationTrackingContext3D> context_owned(
3433 new StrictMock<AllocationTrackingContext3D>);
3434 AllocationTrackingContext3D* context = context_owned.get();
3435 context_owned->set_support_sync_query(true);
3437 FakeOutputSurfaceClient output_surface_client;
3438 scoped_ptr<OutputSurface> output_surface(
3439 FakeOutputSurface::Create3d(context_owned.Pass()));
3440 ASSERT_TRUE(output_surface->BindToClient(&output_surface_client));
3442 const int kWidth = 2;
3443 const int kHeight = 2;
3444 gfx::Size size(kWidth, kHeight);
3445 ResourceFormat format = RGBA_8888;
3446 ResourceProvider::ResourceId source_id = 0;
3447 ResourceProvider::ResourceId dest_id = 0;
3448 const unsigned kSourceTextureId = 123u;
3449 const unsigned kDestTextureId = 321u;
3450 const unsigned kImageId = 234u;
3452 scoped_ptr<ResourceProvider> resource_provider(
3453 ResourceProvider::Create(output_surface.get(),
3454 shared_bitmap_manager_.get(),
3455 gpu_memory_buffer_manager_.get(),
3456 NULL,
3458 false,
3459 1));
3461 source_id = resource_provider->CreateResource(
3462 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
3464 EXPECT_CALL(*context, createImageCHROMIUM(_, kWidth, kHeight, GL_RGBA))
3465 .WillOnce(Return(kImageId))
3466 .RetiresOnSaturation();
3468 ResourceProvider::ScopedWriteLockGpuMemoryBuffer lock(
3469 resource_provider.get(), source_id);
3470 EXPECT_TRUE(!!lock.GetGpuMemoryBuffer());
3472 Mock::VerifyAndClearExpectations(context);
3474 dest_id = resource_provider->CreateResource(
3475 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
3477 EXPECT_CALL(*context, NextTextureId())
3478 .WillOnce(Return(kDestTextureId))
3479 .RetiresOnSaturation();
3480 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kDestTextureId))
3481 .Times(2)
3482 .RetiresOnSaturation();
3483 EXPECT_CALL(*context, texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA,
3484 GL_UNSIGNED_BYTE, nullptr))
3485 .Times(1)
3486 .RetiresOnSaturation();
3487 EXPECT_CALL(*context, NextTextureId())
3488 .WillOnce(Return(kSourceTextureId))
3489 .RetiresOnSaturation();
3490 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kSourceTextureId))
3491 .Times(2)
3492 .RetiresOnSaturation();
3493 EXPECT_CALL(*context, bindTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId))
3494 .Times(1)
3495 .RetiresOnSaturation();
3496 resource_provider->CopyResource(source_id, dest_id);
3497 Mock::VerifyAndClearExpectations(context);
3499 EXPECT_CALL(*context, destroyImageCHROMIUM(kImageId))
3500 .Times(1)
3501 .RetiresOnSaturation();
3502 EXPECT_CALL(*context, RetireTextureId(kSourceTextureId))
3503 .Times(1)
3504 .RetiresOnSaturation();
3505 EXPECT_CALL(*context, RetireTextureId(kDestTextureId))
3506 .Times(1)
3507 .RetiresOnSaturation();
3508 resource_provider->DeleteResource(source_id);
3509 resource_provider->DeleteResource(dest_id);
3512 void InitializeGLAndCheck(ContextSharedData* shared_data,
3513 ResourceProvider* resource_provider,
3514 FakeOutputSurface* output_surface) {
3515 scoped_ptr<ResourceProviderContext> context_owned =
3516 ResourceProviderContext::Create(shared_data);
3517 ResourceProviderContext* context = context_owned.get();
3519 scoped_refptr<TestContextProvider> context_provider =
3520 TestContextProvider::Create(context_owned.Pass());
3521 output_surface->InitializeAndSetContext3d(context_provider);
3522 resource_provider->InitializeGL();
3524 CheckCreateResource(ResourceProvider::GLTexture, resource_provider, context);
3527 TEST(ResourceProviderTest, BasicInitializeGLSoftware) {
3528 scoped_ptr<ContextSharedData> shared_data = ContextSharedData::Create();
3529 bool delegated_rendering = false;
3530 scoped_ptr<FakeOutputSurface> output_surface(
3531 FakeOutputSurface::CreateDeferredGL(
3532 scoped_ptr<SoftwareOutputDevice>(new SoftwareOutputDevice),
3533 delegated_rendering));
3534 FakeOutputSurfaceClient client(output_surface.get());
3535 EXPECT_TRUE(output_surface->BindToClient(&client));
3536 scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
3537 new TestSharedBitmapManager());
3538 scoped_ptr<ResourceProvider> resource_provider(
3539 ResourceProvider::Create(output_surface.get(),
3540 shared_bitmap_manager.get(),
3541 NULL,
3542 NULL,
3544 false,
3545 1));
3547 CheckCreateResource(ResourceProvider::Bitmap, resource_provider.get(), NULL);
3549 InitializeGLAndCheck(shared_data.get(),
3550 resource_provider.get(),
3551 output_surface.get());
3553 resource_provider->InitializeSoftware();
3554 output_surface->ReleaseGL();
3555 CheckCreateResource(ResourceProvider::Bitmap, resource_provider.get(), NULL);
3557 InitializeGLAndCheck(shared_data.get(),
3558 resource_provider.get(),
3559 output_surface.get());
3562 TEST_P(ResourceProviderTest, CompressedTextureETC1Allocate) {
3563 if (GetParam() != ResourceProvider::GLTexture)
3564 return;
3566 scoped_ptr<AllocationTrackingContext3D> context_owned(
3567 new AllocationTrackingContext3D);
3568 AllocationTrackingContext3D* context = context_owned.get();
3569 context_owned->set_support_compressed_texture_etc1(true);
3571 FakeOutputSurfaceClient output_surface_client;
3572 scoped_ptr<OutputSurface> output_surface(
3573 FakeOutputSurface::Create3d(context_owned.Pass()));
3574 CHECK(output_surface->BindToClient(&output_surface_client));
3576 gfx::Size size(4, 4);
3577 scoped_ptr<ResourceProvider> resource_provider(
3578 ResourceProvider::Create(output_surface.get(),
3579 shared_bitmap_manager_.get(),
3580 gpu_memory_buffer_manager_.get(),
3581 NULL,
3583 false,
3584 1));
3585 int texture_id = 123;
3587 ResourceProvider::ResourceId id = resource_provider->CreateResource(
3588 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, ETC1);
3589 EXPECT_NE(0u, id);
3590 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3591 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
3592 resource_provider->AllocateForTesting(id);
3594 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3595 resource_provider->DeleteResource(id);
3598 TEST_P(ResourceProviderTest, CompressedTextureETC1SetPixels) {
3599 if (GetParam() != ResourceProvider::GLTexture)
3600 return;
3602 scoped_ptr<AllocationTrackingContext3D> context_owned(
3603 new AllocationTrackingContext3D);
3604 AllocationTrackingContext3D* context = context_owned.get();
3605 context_owned->set_support_compressed_texture_etc1(true);
3607 FakeOutputSurfaceClient output_surface_client;
3608 scoped_ptr<OutputSurface> output_surface(
3609 FakeOutputSurface::Create3d(context_owned.Pass()));
3610 CHECK(output_surface->BindToClient(&output_surface_client));
3612 gfx::Size size(4, 4);
3613 scoped_ptr<ResourceProvider> resource_provider(
3614 ResourceProvider::Create(output_surface.get(),
3615 shared_bitmap_manager_.get(),
3616 gpu_memory_buffer_manager_.get(),
3617 NULL,
3619 false,
3620 1));
3621 int texture_id = 123;
3622 uint8_t pixels[8];
3624 ResourceProvider::ResourceId id = resource_provider->CreateResource(
3625 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, ETC1);
3626 EXPECT_NE(0u, id);
3627 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3628 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(3);
3629 EXPECT_CALL(*context,
3630 compressedTexImage2D(
3631 _, 0, _, size.width(), size.height(), _, _, _)).Times(1);
3632 resource_provider->SetPixels(
3633 id, pixels, gfx::Rect(size), gfx::Rect(size), gfx::Vector2d(0, 0));
3635 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3636 resource_provider->DeleteResource(id);
3639 INSTANTIATE_TEST_CASE_P(
3640 ResourceProviderTests,
3641 ResourceProviderTest,
3642 ::testing::Values(ResourceProvider::GLTexture, ResourceProvider::Bitmap));
3644 class TextureIdAllocationTrackingContext : public TestWebGraphicsContext3D {
3645 public:
3646 GLuint NextTextureId() override {
3647 base::AutoLock lock(namespace_->lock);
3648 return namespace_->next_texture_id++;
3650 void RetireTextureId(GLuint) override {}
3651 GLuint PeekTextureId() {
3652 base::AutoLock lock(namespace_->lock);
3653 return namespace_->next_texture_id;
3657 TEST(ResourceProviderTest, TextureAllocationChunkSize) {
3658 scoped_ptr<TextureIdAllocationTrackingContext> context_owned(
3659 new TextureIdAllocationTrackingContext);
3660 TextureIdAllocationTrackingContext* context = context_owned.get();
3662 FakeOutputSurfaceClient output_surface_client;
3663 scoped_ptr<OutputSurface> output_surface(
3664 FakeOutputSurface::Create3d(context_owned.Pass()));
3665 CHECK(output_surface->BindToClient(&output_surface_client));
3666 scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
3667 new TestSharedBitmapManager());
3669 gfx::Size size(1, 1);
3670 ResourceFormat format = RGBA_8888;
3673 size_t kTextureAllocationChunkSize = 1;
3674 scoped_ptr<ResourceProvider> resource_provider(
3675 ResourceProvider::Create(output_surface.get(),
3676 shared_bitmap_manager.get(),
3677 NULL,
3678 NULL,
3680 false,
3681 kTextureAllocationChunkSize));
3683 ResourceProvider::ResourceId id = resource_provider->CreateResource(
3684 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
3685 resource_provider->AllocateForTesting(id);
3686 Mock::VerifyAndClearExpectations(context);
3688 DCHECK_EQ(2u, context->PeekTextureId());
3689 resource_provider->DeleteResource(id);
3693 size_t kTextureAllocationChunkSize = 8;
3694 scoped_ptr<ResourceProvider> resource_provider(
3695 ResourceProvider::Create(output_surface.get(),
3696 shared_bitmap_manager.get(),
3697 NULL,
3698 NULL,
3700 false,
3701 kTextureAllocationChunkSize));
3703 ResourceProvider::ResourceId id = resource_provider->CreateResource(
3704 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
3705 resource_provider->AllocateForTesting(id);
3706 Mock::VerifyAndClearExpectations(context);
3708 DCHECK_EQ(10u, context->PeekTextureId());
3709 resource_provider->DeleteResource(id);
3713 } // namespace
3714 } // namespace cc