aw: Move SharedRendererState out of AwContents
[chromium-blink-merge.git] / cc / resources / resource_provider_unittest.cc
blobe507ad67a93558d64c805a6edc69db2be348791a
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 SharedMemoryReleaseCallback(
63 scoped_ptr<base::SharedMemory> memory,
64 uint32 sync_point,
65 bool lost_resource,
66 BlockingTaskRunner* main_thread_task_runner) {
69 static void ReleaseSharedMemoryCallback(
70 scoped_ptr<base::SharedMemory> shared_memory,
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<base::SharedMemory> CreateAndFillSharedMemory(
83 const gfx::Size& size,
84 uint32_t value) {
85 scoped_ptr<base::SharedMemory> shared_memory(new base::SharedMemory);
86 CHECK(shared_memory->CreateAndMapAnonymous(4 * size.GetArea()));
87 uint32_t* pixels = reinterpret_cast<uint32_t*>(shared_memory->memory());
88 CHECK(pixels);
89 std::fill_n(pixels, size.GetArea(), value);
90 return shared_memory.Pass();
93 class TextureStateTrackingContext : public TestWebGraphicsContext3D {
94 public:
95 MOCK_METHOD2(bindTexture, void(GLenum target, GLuint texture));
96 MOCK_METHOD3(texParameteri, void(GLenum target, GLenum pname, GLint param));
97 MOCK_METHOD1(waitSyncPoint, void(GLuint sync_point));
98 MOCK_METHOD0(insertSyncPoint, GLuint(void));
99 MOCK_METHOD2(produceTextureCHROMIUM,
100 void(GLenum target, const GLbyte* mailbox));
101 MOCK_METHOD2(consumeTextureCHROMIUM,
102 void(GLenum target, const GLbyte* mailbox));
104 // Force all textures to be consecutive numbers starting at "1",
105 // so we easily can test for them.
106 virtual GLuint NextTextureId() override {
107 base::AutoLock lock(namespace_->lock);
108 return namespace_->next_texture_id++;
110 virtual void RetireTextureId(GLuint) override {}
113 // Shared data between multiple ResourceProviderContext. This contains mailbox
114 // contents as well as information about sync points.
115 class ContextSharedData {
116 public:
117 static scoped_ptr<ContextSharedData> Create() {
118 return make_scoped_ptr(new ContextSharedData());
121 uint32 InsertSyncPoint() { return next_sync_point_++; }
123 void GenMailbox(GLbyte* mailbox) {
124 memset(mailbox, 0, GL_MAILBOX_SIZE_CHROMIUM);
125 memcpy(mailbox, &next_mailbox_, sizeof(next_mailbox_));
126 ++next_mailbox_;
129 void ProduceTexture(const GLbyte* mailbox_name,
130 uint32 sync_point,
131 scoped_refptr<TestTexture> texture) {
132 unsigned mailbox = 0;
133 memcpy(&mailbox, mailbox_name, sizeof(mailbox));
134 ASSERT_TRUE(mailbox && mailbox < next_mailbox_);
135 textures_[mailbox] = texture;
136 ASSERT_LT(sync_point_for_mailbox_[mailbox], sync_point);
137 sync_point_for_mailbox_[mailbox] = sync_point;
140 scoped_refptr<TestTexture> ConsumeTexture(const GLbyte* mailbox_name,
141 uint32 sync_point) {
142 unsigned mailbox = 0;
143 memcpy(&mailbox, mailbox_name, sizeof(mailbox));
144 DCHECK(mailbox && mailbox < next_mailbox_);
146 // If the latest sync point the context has waited on is before the sync
147 // point for when the mailbox was set, pretend we never saw that
148 // ProduceTexture.
149 if (sync_point_for_mailbox_[mailbox] > sync_point) {
150 NOTREACHED();
151 return scoped_refptr<TestTexture>();
153 return textures_[mailbox];
156 private:
157 ContextSharedData() : next_sync_point_(1), next_mailbox_(1) {}
159 uint32 next_sync_point_;
160 unsigned next_mailbox_;
161 typedef base::hash_map<unsigned, scoped_refptr<TestTexture>> TextureMap;
162 TextureMap textures_;
163 base::hash_map<unsigned, uint32> sync_point_for_mailbox_;
166 class ResourceProviderContext : public TestWebGraphicsContext3D {
167 public:
168 static scoped_ptr<ResourceProviderContext> Create(
169 ContextSharedData* shared_data) {
170 return make_scoped_ptr(new ResourceProviderContext(shared_data));
173 GLuint insertSyncPoint() override {
174 uint32 sync_point = shared_data_->InsertSyncPoint();
175 // Commit the produceTextureCHROMIUM calls at this point, so that
176 // they're associated with the sync point.
177 for (PendingProduceTextureList::iterator it =
178 pending_produce_textures_.begin();
179 it != pending_produce_textures_.end();
180 ++it) {
181 shared_data_->ProduceTexture(
182 (*it)->mailbox, sync_point, (*it)->texture);
184 pending_produce_textures_.clear();
185 return sync_point;
188 void waitSyncPoint(GLuint sync_point) override {
189 last_waited_sync_point_ = std::max(sync_point, last_waited_sync_point_);
192 unsigned last_waited_sync_point() const { return last_waited_sync_point_; }
194 void texStorage2DEXT(GLenum target,
195 GLint levels,
196 GLuint internalformat,
197 GLint width,
198 GLint height) override {
199 CheckTextureIsBound(target);
200 ASSERT_EQ(static_cast<unsigned>(GL_TEXTURE_2D), target);
201 ASSERT_EQ(1, levels);
202 GLenum format = GL_RGBA;
203 switch (internalformat) {
204 case GL_RGBA8_OES:
205 break;
206 case GL_BGRA8_EXT:
207 format = GL_BGRA_EXT;
208 break;
209 default:
210 NOTREACHED();
212 AllocateTexture(gfx::Size(width, height), format);
215 void texImage2D(GLenum target,
216 GLint level,
217 GLenum internalformat,
218 GLsizei width,
219 GLsizei height,
220 GLint border,
221 GLenum format,
222 GLenum type,
223 const void* pixels) override {
224 CheckTextureIsBound(target);
225 ASSERT_EQ(static_cast<unsigned>(GL_TEXTURE_2D), target);
226 ASSERT_FALSE(level);
227 ASSERT_EQ(internalformat, format);
228 ASSERT_FALSE(border);
229 ASSERT_EQ(static_cast<unsigned>(GL_UNSIGNED_BYTE), type);
230 AllocateTexture(gfx::Size(width, height), format);
231 if (pixels)
232 SetPixels(0, 0, width, height, pixels);
235 void texSubImage2D(GLenum target,
236 GLint level,
237 GLint xoffset,
238 GLint yoffset,
239 GLsizei width,
240 GLsizei height,
241 GLenum format,
242 GLenum type,
243 const void* pixels) override {
244 CheckTextureIsBound(target);
245 ASSERT_EQ(static_cast<unsigned>(GL_TEXTURE_2D), target);
246 ASSERT_FALSE(level);
247 ASSERT_EQ(static_cast<unsigned>(GL_UNSIGNED_BYTE), type);
249 base::AutoLock lock_for_texture_access(namespace_->lock);
250 ASSERT_EQ(GLDataFormat(BoundTexture(target)->format), format);
252 ASSERT_TRUE(pixels);
253 SetPixels(xoffset, yoffset, width, height, pixels);
256 void genMailboxCHROMIUM(GLbyte* mailbox) override {
257 return shared_data_->GenMailbox(mailbox);
260 void produceTextureCHROMIUM(GLenum target, const GLbyte* mailbox) override {
261 CheckTextureIsBound(target);
263 // Delay moving the texture into the mailbox until the next
264 // InsertSyncPoint, so that it is not visible to other contexts that
265 // haven't waited on that sync point.
266 scoped_ptr<PendingProduceTexture> pending(new PendingProduceTexture);
267 memcpy(pending->mailbox, mailbox, sizeof(pending->mailbox));
268 base::AutoLock lock_for_texture_access(namespace_->lock);
269 pending->texture = BoundTexture(target);
270 pending_produce_textures_.push_back(pending.Pass());
273 void consumeTextureCHROMIUM(GLenum target, const GLbyte* mailbox) override {
274 CheckTextureIsBound(target);
275 base::AutoLock lock_for_texture_access(namespace_->lock);
276 scoped_refptr<TestTexture> texture =
277 shared_data_->ConsumeTexture(mailbox, last_waited_sync_point_);
278 namespace_->textures.Replace(BoundTextureId(target), texture);
281 void GetPixels(const gfx::Size& size,
282 ResourceFormat format,
283 uint8_t* pixels) {
284 CheckTextureIsBound(GL_TEXTURE_2D);
285 base::AutoLock lock_for_texture_access(namespace_->lock);
286 scoped_refptr<TestTexture> texture = BoundTexture(GL_TEXTURE_2D);
287 ASSERT_EQ(texture->size, size);
288 ASSERT_EQ(texture->format, format);
289 memcpy(pixels, texture->data.get(), TextureSizeBytes(size, format));
292 protected:
293 explicit ResourceProviderContext(ContextSharedData* shared_data)
294 : shared_data_(shared_data),
295 last_waited_sync_point_(0) {}
297 private:
298 void AllocateTexture(const gfx::Size& size, GLenum format) {
299 CheckTextureIsBound(GL_TEXTURE_2D);
300 ResourceFormat texture_format = RGBA_8888;
301 switch (format) {
302 case GL_RGBA:
303 texture_format = RGBA_8888;
304 break;
305 case GL_BGRA_EXT:
306 texture_format = BGRA_8888;
307 break;
309 base::AutoLock lock_for_texture_access(namespace_->lock);
310 BoundTexture(GL_TEXTURE_2D)->Reallocate(size, texture_format);
313 void SetPixels(int xoffset,
314 int yoffset,
315 int width,
316 int height,
317 const void* pixels) {
318 CheckTextureIsBound(GL_TEXTURE_2D);
319 base::AutoLock lock_for_texture_access(namespace_->lock);
320 scoped_refptr<TestTexture> texture = BoundTexture(GL_TEXTURE_2D);
321 ASSERT_TRUE(texture->data.get());
322 ASSERT_TRUE(xoffset >= 0 && xoffset + width <= texture->size.width());
323 ASSERT_TRUE(yoffset >= 0 && yoffset + height <= texture->size.height());
324 ASSERT_TRUE(pixels);
325 size_t in_pitch = TextureSizeBytes(gfx::Size(width, 1), texture->format);
326 size_t out_pitch =
327 TextureSizeBytes(gfx::Size(texture->size.width(), 1), texture->format);
328 uint8_t* dest = texture->data.get() + yoffset * out_pitch +
329 TextureSizeBytes(gfx::Size(xoffset, 1), texture->format);
330 const uint8_t* src = static_cast<const uint8_t*>(pixels);
331 for (int i = 0; i < height; ++i) {
332 memcpy(dest, src, in_pitch);
333 dest += out_pitch;
334 src += in_pitch;
338 struct PendingProduceTexture {
339 GLbyte mailbox[GL_MAILBOX_SIZE_CHROMIUM];
340 scoped_refptr<TestTexture> texture;
342 typedef ScopedPtrDeque<PendingProduceTexture> PendingProduceTextureList;
343 ContextSharedData* shared_data_;
344 GLuint last_waited_sync_point_;
345 PendingProduceTextureList pending_produce_textures_;
348 void GetResourcePixels(ResourceProvider* resource_provider,
349 ResourceProviderContext* context,
350 ResourceProvider::ResourceId id,
351 const gfx::Size& size,
352 ResourceFormat format,
353 uint8_t* pixels) {
354 resource_provider->WaitSyncPointIfNeeded(id);
355 switch (resource_provider->default_resource_type()) {
356 case ResourceProvider::GLTexture: {
357 ResourceProvider::ScopedReadLockGL lock_gl(resource_provider, id);
358 ASSERT_NE(0U, lock_gl.texture_id());
359 context->bindTexture(GL_TEXTURE_2D, lock_gl.texture_id());
360 context->GetPixels(size, format, pixels);
361 break;
363 case ResourceProvider::Bitmap: {
364 ResourceProvider::ScopedReadLockSoftware lock_software(resource_provider,
365 id);
366 memcpy(pixels,
367 lock_software.sk_bitmap()->getPixels(),
368 lock_software.sk_bitmap()->getSize());
369 break;
371 case ResourceProvider::InvalidType:
372 NOTREACHED();
373 break;
377 class ResourceProviderTest
378 : public testing::TestWithParam<ResourceProvider::ResourceType> {
379 public:
380 ResourceProviderTest()
381 : shared_data_(ContextSharedData::Create()),
382 context3d_(NULL),
383 child_context_(NULL),
384 main_thread_task_runner_(BlockingTaskRunner::Create(NULL)) {
385 switch (GetParam()) {
386 case ResourceProvider::GLTexture: {
387 scoped_ptr<ResourceProviderContext> context3d(
388 ResourceProviderContext::Create(shared_data_.get()));
389 context3d_ = context3d.get();
391 scoped_refptr<TestContextProvider> context_provider =
392 TestContextProvider::Create(context3d.Pass());
394 output_surface_ = FakeOutputSurface::Create3d(context_provider);
396 scoped_ptr<ResourceProviderContext> child_context_owned =
397 ResourceProviderContext::Create(shared_data_.get());
398 child_context_ = child_context_owned.get();
399 child_output_surface_ =
400 FakeOutputSurface::Create3d(child_context_owned.Pass());
401 break;
403 case ResourceProvider::Bitmap:
404 output_surface_ = FakeOutputSurface::CreateSoftware(
405 make_scoped_ptr(new SoftwareOutputDevice));
406 child_output_surface_ = FakeOutputSurface::CreateSoftware(
407 make_scoped_ptr(new SoftwareOutputDevice));
408 break;
409 case ResourceProvider::InvalidType:
410 NOTREACHED();
411 break;
413 CHECK(output_surface_->BindToClient(&output_surface_client_));
414 CHECK(child_output_surface_->BindToClient(&child_output_surface_client_));
416 shared_bitmap_manager_.reset(new TestSharedBitmapManager);
417 gpu_memory_buffer_manager_.reset(new TestGpuMemoryBufferManager);
419 resource_provider_ =
420 ResourceProvider::Create(output_surface_.get(),
421 shared_bitmap_manager_.get(),
422 gpu_memory_buffer_manager_.get(),
423 main_thread_task_runner_.get(),
425 false,
427 child_resource_provider_ =
428 ResourceProvider::Create(child_output_surface_.get(),
429 shared_bitmap_manager_.get(),
430 gpu_memory_buffer_manager_.get(),
431 main_thread_task_runner_.get(),
433 false,
437 static void CollectResources(ReturnedResourceArray* array,
438 const ReturnedResourceArray& returned,
439 BlockingTaskRunner* main_thread_task_runner) {
440 array->insert(array->end(), returned.begin(), returned.end());
443 static ReturnCallback GetReturnCallback(ReturnedResourceArray* array) {
444 return base::Bind(&ResourceProviderTest::CollectResources, array);
447 static void SetResourceFilter(ResourceProvider* resource_provider,
448 ResourceProvider::ResourceId id,
449 GLenum filter) {
450 ResourceProvider::ScopedSamplerGL sampler(
451 resource_provider, id, GL_TEXTURE_2D, filter);
454 ResourceProviderContext* context() { return context3d_; }
456 ResourceProvider::ResourceId CreateChildMailbox(uint32* release_sync_point,
457 bool* lost_resource,
458 bool* release_called,
459 uint32* sync_point) {
460 if (GetParam() == ResourceProvider::GLTexture) {
461 unsigned texture = child_context_->createTexture();
462 gpu::Mailbox gpu_mailbox;
463 child_context_->bindTexture(GL_TEXTURE_2D, texture);
464 child_context_->genMailboxCHROMIUM(gpu_mailbox.name);
465 child_context_->produceTextureCHROMIUM(GL_TEXTURE_2D, gpu_mailbox.name);
466 *sync_point = child_context_->insertSyncPoint();
467 EXPECT_LT(0u, *sync_point);
469 scoped_ptr<base::SharedMemory> shared_memory;
470 scoped_ptr<SingleReleaseCallbackImpl> callback =
471 SingleReleaseCallbackImpl::Create(
472 base::Bind(ReleaseSharedMemoryCallback,
473 base::Passed(&shared_memory),
474 release_called,
475 release_sync_point,
476 lost_resource));
477 return child_resource_provider_->CreateResourceFromTextureMailbox(
478 TextureMailbox(gpu_mailbox, GL_TEXTURE_2D, *sync_point),
479 callback.Pass());
480 } else {
481 gfx::Size size(64, 64);
482 scoped_ptr<base::SharedMemory> shared_memory(
483 CreateAndFillSharedMemory(size, 0));
485 base::SharedMemory* shared_memory_ptr = shared_memory.get();
486 scoped_ptr<SingleReleaseCallbackImpl> callback =
487 SingleReleaseCallbackImpl::Create(
488 base::Bind(ReleaseSharedMemoryCallback,
489 base::Passed(&shared_memory),
490 release_called,
491 release_sync_point,
492 lost_resource));
493 return child_resource_provider_->CreateResourceFromTextureMailbox(
494 TextureMailbox(shared_memory_ptr, size), callback.Pass());
498 protected:
499 scoped_ptr<ContextSharedData> shared_data_;
500 ResourceProviderContext* context3d_;
501 ResourceProviderContext* child_context_;
502 FakeOutputSurfaceClient output_surface_client_;
503 FakeOutputSurfaceClient child_output_surface_client_;
504 scoped_ptr<OutputSurface> output_surface_;
505 scoped_ptr<OutputSurface> child_output_surface_;
506 scoped_ptr<BlockingTaskRunner> main_thread_task_runner_;
507 scoped_ptr<ResourceProvider> resource_provider_;
508 scoped_ptr<ResourceProvider> child_resource_provider_;
509 scoped_ptr<TestSharedBitmapManager> shared_bitmap_manager_;
510 scoped_ptr<TestGpuMemoryBufferManager> gpu_memory_buffer_manager_;
513 void CheckCreateResource(ResourceProvider::ResourceType expected_default_type,
514 ResourceProvider* resource_provider,
515 ResourceProviderContext* context) {
516 DCHECK_EQ(expected_default_type, resource_provider->default_resource_type());
518 gfx::Size size(1, 1);
519 ResourceFormat format = RGBA_8888;
520 size_t pixel_size = TextureSizeBytes(size, format);
521 ASSERT_EQ(4U, pixel_size);
523 ResourceProvider::ResourceId id = resource_provider->CreateResource(
524 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
525 EXPECT_EQ(1, static_cast<int>(resource_provider->num_resources()));
526 if (expected_default_type == ResourceProvider::GLTexture)
527 EXPECT_EQ(0u, context->NumTextures());
529 uint8_t data[4] = { 1, 2, 3, 4 };
530 gfx::Rect rect(size);
531 resource_provider->SetPixels(id, data, rect, rect, gfx::Vector2d());
532 if (expected_default_type == ResourceProvider::GLTexture)
533 EXPECT_EQ(1u, context->NumTextures());
535 uint8_t result[4] = { 0 };
536 GetResourcePixels(resource_provider, context, id, size, format, result);
537 EXPECT_EQ(0, memcmp(data, result, pixel_size));
539 resource_provider->DeleteResource(id);
540 EXPECT_EQ(0, static_cast<int>(resource_provider->num_resources()));
541 if (expected_default_type == ResourceProvider::GLTexture)
542 EXPECT_EQ(0u, context->NumTextures());
545 TEST_P(ResourceProviderTest, Basic) {
546 CheckCreateResource(GetParam(), resource_provider_.get(), context());
549 TEST_P(ResourceProviderTest, Upload) {
550 gfx::Size size(2, 2);
551 ResourceFormat format = RGBA_8888;
552 size_t pixel_size = TextureSizeBytes(size, format);
553 ASSERT_EQ(16U, pixel_size);
555 ResourceProvider::ResourceId id = resource_provider_->CreateResource(
556 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
558 uint8_t image[16] = { 0 };
559 gfx::Rect image_rect(size);
560 resource_provider_->SetPixels(
561 id, image, image_rect, image_rect, gfx::Vector2d());
563 for (uint8_t i = 0; i < pixel_size; ++i)
564 image[i] = i;
566 uint8_t result[16] = { 0 };
568 gfx::Rect source_rect(0, 0, 1, 1);
569 gfx::Vector2d dest_offset(0, 0);
570 resource_provider_->SetPixels(
571 id, image, image_rect, source_rect, dest_offset);
573 uint8_t expected[16] = { 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
574 GetResourcePixels(
575 resource_provider_.get(), context(), id, size, format, result);
576 EXPECT_EQ(0, memcmp(expected, result, pixel_size));
579 gfx::Rect source_rect(0, 0, 1, 1);
580 gfx::Vector2d dest_offset(1, 1);
581 resource_provider_->SetPixels(
582 id, image, image_rect, source_rect, dest_offset);
584 uint8_t expected[16] = { 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3 };
585 GetResourcePixels(
586 resource_provider_.get(), context(), id, size, format, result);
587 EXPECT_EQ(0, memcmp(expected, result, pixel_size));
590 gfx::Rect source_rect(1, 0, 1, 1);
591 gfx::Vector2d dest_offset(0, 1);
592 resource_provider_->SetPixels(
593 id, image, image_rect, source_rect, dest_offset);
595 uint8_t expected[16] = { 0, 1, 2, 3, 0, 0, 0, 0, 4, 5, 6, 7, 0, 1, 2, 3 };
596 GetResourcePixels(
597 resource_provider_.get(), context(), id, size, format, result);
598 EXPECT_EQ(0, memcmp(expected, result, pixel_size));
601 gfx::Rect offset_image_rect(gfx::Point(100, 100), size);
602 gfx::Rect source_rect(100, 100, 1, 1);
603 gfx::Vector2d dest_offset(1, 0);
604 resource_provider_->SetPixels(
605 id, image, offset_image_rect, source_rect, dest_offset);
607 uint8_t expected[16] = { 0, 1, 2, 3, 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3 };
608 GetResourcePixels(
609 resource_provider_.get(), context(), id, size, format, result);
610 EXPECT_EQ(0, memcmp(expected, result, pixel_size));
613 resource_provider_->DeleteResource(id);
616 TEST_P(ResourceProviderTest, TransferGLResources) {
617 if (GetParam() != ResourceProvider::GLTexture)
618 return;
619 gfx::Size size(1, 1);
620 ResourceFormat format = RGBA_8888;
621 size_t pixel_size = TextureSizeBytes(size, format);
622 ASSERT_EQ(4U, pixel_size);
624 ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource(
625 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
626 uint8_t data1[4] = { 1, 2, 3, 4 };
627 gfx::Rect rect(size);
628 child_resource_provider_->SetPixels(id1, data1, rect, rect, gfx::Vector2d());
630 ResourceProvider::ResourceId id2 = child_resource_provider_->CreateResource(
631 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
632 uint8_t data2[4] = { 5, 5, 5, 5 };
633 child_resource_provider_->SetPixels(id2, data2, rect, rect, gfx::Vector2d());
635 ResourceProvider::ResourceId id3 = child_resource_provider_->CreateResource(
636 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
638 ResourceProvider::ScopedWriteLockGpuMemoryBuffer lock(
639 child_resource_provider_.get(), id3);
640 EXPECT_TRUE(!!lock.GetGpuMemoryBuffer());
643 GLuint external_texture_id = child_context_->createExternalTexture();
644 child_context_->bindTexture(GL_TEXTURE_EXTERNAL_OES, external_texture_id);
646 gpu::Mailbox external_mailbox;
647 child_context_->genMailboxCHROMIUM(external_mailbox.name);
648 child_context_->produceTextureCHROMIUM(GL_TEXTURE_EXTERNAL_OES,
649 external_mailbox.name);
650 const GLuint external_sync_point = child_context_->insertSyncPoint();
651 ResourceProvider::ResourceId id4 =
652 child_resource_provider_->CreateResourceFromTextureMailbox(
653 TextureMailbox(
654 external_mailbox, GL_TEXTURE_EXTERNAL_OES, external_sync_point),
655 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback)));
657 ReturnedResourceArray returned_to_child;
658 int child_id =
659 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
661 // Transfer some resources to the parent.
662 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
663 resource_ids_to_transfer.push_back(id1);
664 resource_ids_to_transfer.push_back(id2);
665 resource_ids_to_transfer.push_back(id3);
666 resource_ids_to_transfer.push_back(id4);
667 TransferableResourceArray list;
668 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
669 &list);
670 ASSERT_EQ(4u, list.size());
671 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
672 EXPECT_NE(0u, list[1].mailbox_holder.sync_point);
673 EXPECT_EQ(list[0].mailbox_holder.sync_point,
674 list[1].mailbox_holder.sync_point);
675 EXPECT_NE(0u, list[2].mailbox_holder.sync_point);
676 EXPECT_EQ(list[0].mailbox_holder.sync_point,
677 list[2].mailbox_holder.sync_point);
678 EXPECT_EQ(external_sync_point, list[3].mailbox_holder.sync_point);
679 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
680 list[0].mailbox_holder.texture_target);
681 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
682 list[1].mailbox_holder.texture_target);
683 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
684 list[2].mailbox_holder.texture_target);
685 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_EXTERNAL_OES),
686 list[3].mailbox_holder.texture_target);
687 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
688 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
689 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
690 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id4));
691 resource_provider_->ReceiveFromChild(child_id, list);
692 EXPECT_NE(list[0].mailbox_holder.sync_point,
693 context3d_->last_waited_sync_point());
695 resource_provider_->WaitSyncPointIfNeeded(list[0].id);
696 ResourceProvider::ScopedReadLockGL lock(resource_provider_.get(),
697 list[0].id);
699 EXPECT_EQ(list[0].mailbox_holder.sync_point,
700 context3d_->last_waited_sync_point());
701 resource_provider_->DeclareUsedResourcesFromChild(child_id,
702 resource_ids_to_transfer);
705 EXPECT_EQ(4u, resource_provider_->num_resources());
706 ResourceProvider::ResourceIdMap resource_map =
707 resource_provider_->GetChildToParentMap(child_id);
708 ResourceProvider::ResourceId mapped_id1 = resource_map[id1];
709 ResourceProvider::ResourceId mapped_id2 = resource_map[id2];
710 ResourceProvider::ResourceId mapped_id3 = resource_map[id3];
711 ResourceProvider::ResourceId mapped_id4 = resource_map[id4];
712 EXPECT_NE(0u, mapped_id1);
713 EXPECT_NE(0u, mapped_id2);
714 EXPECT_NE(0u, mapped_id3);
715 EXPECT_NE(0u, mapped_id4);
716 EXPECT_FALSE(resource_provider_->InUseByConsumer(id1));
717 EXPECT_FALSE(resource_provider_->InUseByConsumer(id2));
718 EXPECT_FALSE(resource_provider_->InUseByConsumer(id3));
719 EXPECT_FALSE(resource_provider_->InUseByConsumer(id4));
721 uint8_t result[4] = { 0 };
722 GetResourcePixels(
723 resource_provider_.get(), context(), mapped_id1, size, format, result);
724 EXPECT_EQ(0, memcmp(data1, result, pixel_size));
726 GetResourcePixels(
727 resource_provider_.get(), context(), mapped_id2, size, format, result);
728 EXPECT_EQ(0, memcmp(data2, result, pixel_size));
731 // Check that transfering again the same resource from the child to the
732 // parent works.
733 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
734 resource_ids_to_transfer.push_back(id1);
735 resource_ids_to_transfer.push_back(id2);
736 resource_ids_to_transfer.push_back(id3);
737 TransferableResourceArray list;
738 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
739 &list);
740 EXPECT_EQ(3u, list.size());
741 EXPECT_EQ(id1, list[0].id);
742 EXPECT_EQ(id2, list[1].id);
743 EXPECT_EQ(id3, list[2].id);
744 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
745 list[0].mailbox_holder.texture_target);
746 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
747 list[1].mailbox_holder.texture_target);
748 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
749 list[2].mailbox_holder.texture_target);
750 ReturnedResourceArray returned;
751 TransferableResource::ReturnResources(list, &returned);
752 child_resource_provider_->ReceiveReturnsFromParent(returned);
753 // ids were exported twice, we returned them only once, they should still
754 // be in-use.
755 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
756 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
757 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
760 EXPECT_EQ(0u, returned_to_child.size());
762 // Transfer resources back from the parent to the child. Set no resources as
763 // being in use.
764 ResourceProvider::ResourceIdArray no_resources;
765 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
767 ASSERT_EQ(4u, returned_to_child.size());
768 EXPECT_NE(0u, returned_to_child[0].sync_point);
769 EXPECT_NE(0u, returned_to_child[1].sync_point);
770 EXPECT_NE(0u, returned_to_child[2].sync_point);
771 EXPECT_NE(0u, returned_to_child[3].sync_point);
772 EXPECT_FALSE(returned_to_child[0].lost);
773 EXPECT_FALSE(returned_to_child[1].lost);
774 EXPECT_FALSE(returned_to_child[2].lost);
775 EXPECT_FALSE(returned_to_child[3].lost);
776 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
777 returned_to_child.clear();
779 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id1));
780 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id2));
781 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id3));
782 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id4));
785 child_resource_provider_->WaitSyncPointIfNeeded(id1);
786 ResourceProvider::ScopedReadLockGL lock(child_resource_provider_.get(),
787 id1);
788 ASSERT_NE(0U, lock.texture_id());
789 child_context_->bindTexture(GL_TEXTURE_2D, lock.texture_id());
790 child_context_->GetPixels(size, format, result);
791 EXPECT_EQ(0, memcmp(data1, result, pixel_size));
794 child_resource_provider_->WaitSyncPointIfNeeded(id2);
795 ResourceProvider::ScopedReadLockGL lock(child_resource_provider_.get(),
796 id2);
797 ASSERT_NE(0U, lock.texture_id());
798 child_context_->bindTexture(GL_TEXTURE_2D, lock.texture_id());
799 child_context_->GetPixels(size, format, result);
800 EXPECT_EQ(0, memcmp(data2, result, pixel_size));
803 child_resource_provider_->WaitSyncPointIfNeeded(id3);
804 ResourceProvider::ScopedReadLockGL lock(child_resource_provider_.get(),
805 id3);
806 ASSERT_NE(0U, lock.texture_id());
807 child_context_->bindTexture(GL_TEXTURE_2D, lock.texture_id());
810 // Transfer resources to the parent again.
811 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
812 resource_ids_to_transfer.push_back(id1);
813 resource_ids_to_transfer.push_back(id2);
814 resource_ids_to_transfer.push_back(id3);
815 resource_ids_to_transfer.push_back(id4);
816 TransferableResourceArray list;
817 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
818 &list);
819 ASSERT_EQ(4u, list.size());
820 EXPECT_EQ(id1, list[0].id);
821 EXPECT_EQ(id2, list[1].id);
822 EXPECT_EQ(id3, list[2].id);
823 EXPECT_EQ(id4, list[3].id);
824 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
825 EXPECT_NE(0u, list[1].mailbox_holder.sync_point);
826 EXPECT_NE(0u, list[2].mailbox_holder.sync_point);
827 EXPECT_NE(0u, list[3].mailbox_holder.sync_point);
828 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
829 list[0].mailbox_holder.texture_target);
830 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
831 list[1].mailbox_holder.texture_target);
832 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
833 list[2].mailbox_holder.texture_target);
834 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_EXTERNAL_OES),
835 list[3].mailbox_holder.texture_target);
836 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
837 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
838 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
839 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id4));
840 resource_provider_->ReceiveFromChild(child_id, list);
841 resource_provider_->DeclareUsedResourcesFromChild(child_id,
842 resource_ids_to_transfer);
845 EXPECT_EQ(0u, returned_to_child.size());
847 EXPECT_EQ(4u, resource_provider_->num_resources());
848 resource_provider_->DestroyChild(child_id);
849 EXPECT_EQ(0u, resource_provider_->num_resources());
851 ASSERT_EQ(4u, returned_to_child.size());
852 EXPECT_NE(0u, returned_to_child[0].sync_point);
853 EXPECT_NE(0u, returned_to_child[1].sync_point);
854 EXPECT_NE(0u, returned_to_child[2].sync_point);
855 EXPECT_NE(0u, returned_to_child[3].sync_point);
856 EXPECT_FALSE(returned_to_child[0].lost);
857 EXPECT_FALSE(returned_to_child[1].lost);
858 EXPECT_FALSE(returned_to_child[2].lost);
859 EXPECT_FALSE(returned_to_child[3].lost);
862 TEST_P(ResourceProviderTest, ReadLockCountStopsReturnToChildOrDelete) {
863 if (GetParam() != ResourceProvider::GLTexture)
864 return;
865 gfx::Size size(1, 1);
866 ResourceFormat format = RGBA_8888;
868 ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource(
869 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
870 uint8_t data1[4] = {1, 2, 3, 4};
871 gfx::Rect rect(size);
872 child_resource_provider_->SetPixels(id1, data1, rect, rect, gfx::Vector2d());
874 ReturnedResourceArray returned_to_child;
875 int child_id =
876 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
878 // Transfer some resources to the parent.
879 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
880 resource_ids_to_transfer.push_back(id1);
881 TransferableResourceArray list;
882 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
883 &list);
884 ASSERT_EQ(1u, list.size());
885 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
887 resource_provider_->ReceiveFromChild(child_id, list);
889 resource_provider_->WaitSyncPointIfNeeded(list[0].id);
890 ResourceProvider::ScopedReadLockGL lock(resource_provider_.get(),
891 list[0].id);
893 resource_provider_->DeclareUsedResourcesFromChild(
894 child_id, ResourceProvider::ResourceIdArray());
895 EXPECT_EQ(0u, returned_to_child.size());
898 EXPECT_EQ(1u, returned_to_child.size());
899 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
902 child_resource_provider_->WaitSyncPointIfNeeded(id1);
903 ResourceProvider::ScopedReadLockGL lock(child_resource_provider_.get(),
904 id1);
905 child_resource_provider_->DeleteResource(id1);
906 EXPECT_EQ(1u, child_resource_provider_->num_resources());
907 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
910 EXPECT_EQ(0u, child_resource_provider_->num_resources());
911 resource_provider_->DestroyChild(child_id);
914 TEST_P(ResourceProviderTest, AllowOverlayTransfersToParent) {
915 // Overlays only supported on the GL path.
916 if (GetParam() != ResourceProvider::GLTexture)
917 return;
919 uint32 sync_point = 0;
920 TextureMailbox mailbox(gpu::Mailbox::Generate(), GL_TEXTURE_2D, sync_point);
921 mailbox.set_allow_overlay(true);
922 scoped_ptr<SingleReleaseCallbackImpl> release_callback =
923 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback));
924 ResourceProvider::ResourceId id1 =
925 child_resource_provider_->CreateResourceFromTextureMailbox(
926 mailbox, release_callback.Pass());
928 TextureMailbox mailbox2(gpu::Mailbox::Generate(), GL_TEXTURE_2D, sync_point);
929 mailbox2.set_allow_overlay(false);
930 scoped_ptr<SingleReleaseCallbackImpl> release_callback2 =
931 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback));
932 ResourceProvider::ResourceId id2 =
933 child_resource_provider_->CreateResourceFromTextureMailbox(
934 mailbox2, release_callback2.Pass());
936 ReturnedResourceArray returned_to_child;
937 int child_id =
938 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
940 // Transfer some resources to the parent.
941 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
942 resource_ids_to_transfer.push_back(id1);
943 resource_ids_to_transfer.push_back(id2);
944 TransferableResourceArray list;
945 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
946 &list);
947 ASSERT_EQ(2u, list.size());
948 resource_provider_->ReceiveFromChild(child_id, list);
949 EXPECT_TRUE(resource_provider_->AllowOverlay(list[0].id));
950 EXPECT_FALSE(resource_provider_->AllowOverlay(list[1].id));
952 resource_provider_->DeclareUsedResourcesFromChild(
953 child_id, ResourceProvider::ResourceIdArray());
955 EXPECT_EQ(2u, returned_to_child.size());
956 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
958 child_resource_provider_->DeleteResource(id1);
959 child_resource_provider_->DeleteResource(id2);
960 EXPECT_EQ(0u, child_resource_provider_->num_resources());
962 resource_provider_->DestroyChild(child_id);
965 TEST_P(ResourceProviderTest, TransferSoftwareResources) {
966 if (GetParam() != ResourceProvider::Bitmap)
967 return;
969 gfx::Size size(1, 1);
970 ResourceFormat format = RGBA_8888;
971 size_t pixel_size = TextureSizeBytes(size, format);
972 ASSERT_EQ(4U, pixel_size);
974 ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource(
975 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
976 uint8_t data1[4] = { 1, 2, 3, 4 };
977 gfx::Rect rect(size);
978 child_resource_provider_->SetPixels(id1, data1, rect, rect, gfx::Vector2d());
980 ResourceProvider::ResourceId id2 = child_resource_provider_->CreateResource(
981 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
982 uint8_t data2[4] = { 5, 5, 5, 5 };
983 child_resource_provider_->SetPixels(id2, data2, rect, rect, gfx::Vector2d());
985 scoped_ptr<base::SharedMemory> shared_memory(new base::SharedMemory());
986 shared_memory->CreateAndMapAnonymous(1);
987 base::SharedMemory* shared_memory_ptr = shared_memory.get();
988 ResourceProvider::ResourceId id3 =
989 child_resource_provider_->CreateResourceFromTextureMailbox(
990 TextureMailbox(shared_memory_ptr, gfx::Size(1, 1)),
991 SingleReleaseCallbackImpl::Create(base::Bind(
992 &SharedMemoryReleaseCallback, base::Passed(&shared_memory))));
994 ReturnedResourceArray returned_to_child;
995 int child_id =
996 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
998 // Transfer some resources to the parent.
999 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1000 resource_ids_to_transfer.push_back(id1);
1001 resource_ids_to_transfer.push_back(id2);
1002 resource_ids_to_transfer.push_back(id3);
1003 TransferableResourceArray list;
1004 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1005 &list);
1006 ASSERT_EQ(3u, list.size());
1007 EXPECT_EQ(0u, list[0].mailbox_holder.sync_point);
1008 EXPECT_EQ(0u, list[1].mailbox_holder.sync_point);
1009 EXPECT_EQ(0u, list[2].mailbox_holder.sync_point);
1010 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1011 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
1012 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
1013 resource_provider_->ReceiveFromChild(child_id, list);
1014 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1015 resource_ids_to_transfer);
1018 EXPECT_EQ(3u, resource_provider_->num_resources());
1019 ResourceProvider::ResourceIdMap resource_map =
1020 resource_provider_->GetChildToParentMap(child_id);
1021 ResourceProvider::ResourceId mapped_id1 = resource_map[id1];
1022 ResourceProvider::ResourceId mapped_id2 = resource_map[id2];
1023 ResourceProvider::ResourceId mapped_id3 = resource_map[id3];
1024 EXPECT_NE(0u, mapped_id1);
1025 EXPECT_NE(0u, mapped_id2);
1026 EXPECT_NE(0u, mapped_id3);
1027 EXPECT_FALSE(resource_provider_->InUseByConsumer(id1));
1028 EXPECT_FALSE(resource_provider_->InUseByConsumer(id2));
1029 EXPECT_FALSE(resource_provider_->InUseByConsumer(id3));
1031 uint8_t result[4] = { 0 };
1032 GetResourcePixels(
1033 resource_provider_.get(), context(), mapped_id1, size, format, result);
1034 EXPECT_EQ(0, memcmp(data1, result, pixel_size));
1036 GetResourcePixels(
1037 resource_provider_.get(), context(), mapped_id2, size, format, result);
1038 EXPECT_EQ(0, memcmp(data2, result, pixel_size));
1041 // Check that transfering again the same resource from the child to the
1042 // parent works.
1043 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1044 resource_ids_to_transfer.push_back(id1);
1045 resource_ids_to_transfer.push_back(id2);
1046 TransferableResourceArray list;
1047 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1048 &list);
1049 EXPECT_EQ(2u, list.size());
1050 EXPECT_EQ(id1, list[0].id);
1051 EXPECT_EQ(id2, list[1].id);
1052 ReturnedResourceArray returned;
1053 TransferableResource::ReturnResources(list, &returned);
1054 child_resource_provider_->ReceiveReturnsFromParent(returned);
1055 // ids were exported twice, we returned them only once, they should still
1056 // be in-use.
1057 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1058 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
1061 EXPECT_EQ(0u, returned_to_child.size());
1063 // Transfer resources back from the parent to the child. Set no resources as
1064 // being in use.
1065 ResourceProvider::ResourceIdArray no_resources;
1066 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
1068 ASSERT_EQ(3u, returned_to_child.size());
1069 EXPECT_EQ(0u, returned_to_child[0].sync_point);
1070 EXPECT_EQ(0u, returned_to_child[1].sync_point);
1071 EXPECT_EQ(0u, returned_to_child[2].sync_point);
1072 std::set<ResourceProvider::ResourceId> expected_ids;
1073 expected_ids.insert(id1);
1074 expected_ids.insert(id2);
1075 expected_ids.insert(id3);
1076 std::set<ResourceProvider::ResourceId> returned_ids;
1077 for (unsigned i = 0; i < 3; i++)
1078 returned_ids.insert(returned_to_child[i].id);
1079 EXPECT_EQ(expected_ids, returned_ids);
1080 EXPECT_FALSE(returned_to_child[0].lost);
1081 EXPECT_FALSE(returned_to_child[1].lost);
1082 EXPECT_FALSE(returned_to_child[2].lost);
1083 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
1084 returned_to_child.clear();
1086 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id1));
1087 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id2));
1088 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id3));
1091 ResourceProvider::ScopedReadLockSoftware lock(
1092 child_resource_provider_.get(), id1);
1093 const SkBitmap* sk_bitmap = lock.sk_bitmap();
1094 EXPECT_EQ(sk_bitmap->width(), size.width());
1095 EXPECT_EQ(sk_bitmap->height(), size.height());
1096 EXPECT_EQ(0, memcmp(data1, sk_bitmap->getPixels(), pixel_size));
1099 ResourceProvider::ScopedReadLockSoftware lock(
1100 child_resource_provider_.get(), id2);
1101 const SkBitmap* sk_bitmap = lock.sk_bitmap();
1102 EXPECT_EQ(sk_bitmap->width(), size.width());
1103 EXPECT_EQ(sk_bitmap->height(), size.height());
1104 EXPECT_EQ(0, memcmp(data2, sk_bitmap->getPixels(), pixel_size));
1107 // Transfer resources to the parent again.
1108 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1109 resource_ids_to_transfer.push_back(id1);
1110 resource_ids_to_transfer.push_back(id2);
1111 resource_ids_to_transfer.push_back(id3);
1112 TransferableResourceArray list;
1113 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1114 &list);
1115 ASSERT_EQ(3u, list.size());
1116 EXPECT_EQ(id1, list[0].id);
1117 EXPECT_EQ(id2, list[1].id);
1118 EXPECT_EQ(id3, list[2].id);
1119 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1120 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
1121 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
1122 resource_provider_->ReceiveFromChild(child_id, list);
1123 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1124 resource_ids_to_transfer);
1127 EXPECT_EQ(0u, returned_to_child.size());
1129 EXPECT_EQ(3u, resource_provider_->num_resources());
1130 resource_provider_->DestroyChild(child_id);
1131 EXPECT_EQ(0u, resource_provider_->num_resources());
1133 ASSERT_EQ(3u, returned_to_child.size());
1134 EXPECT_EQ(0u, returned_to_child[0].sync_point);
1135 EXPECT_EQ(0u, returned_to_child[1].sync_point);
1136 EXPECT_EQ(0u, returned_to_child[2].sync_point);
1137 std::set<ResourceProvider::ResourceId> expected_ids;
1138 expected_ids.insert(id1);
1139 expected_ids.insert(id2);
1140 expected_ids.insert(id3);
1141 std::set<ResourceProvider::ResourceId> returned_ids;
1142 for (unsigned i = 0; i < 3; i++)
1143 returned_ids.insert(returned_to_child[i].id);
1144 EXPECT_EQ(expected_ids, returned_ids);
1145 EXPECT_FALSE(returned_to_child[0].lost);
1146 EXPECT_FALSE(returned_to_child[1].lost);
1147 EXPECT_FALSE(returned_to_child[2].lost);
1150 TEST_P(ResourceProviderTest, TransferGLToSoftware) {
1151 if (GetParam() != ResourceProvider::Bitmap)
1152 return;
1154 scoped_ptr<ResourceProviderContext> child_context_owned(
1155 ResourceProviderContext::Create(shared_data_.get()));
1157 FakeOutputSurfaceClient child_output_surface_client;
1158 scoped_ptr<OutputSurface> child_output_surface(
1159 FakeOutputSurface::Create3d(child_context_owned.Pass()));
1160 CHECK(child_output_surface->BindToClient(&child_output_surface_client));
1162 scoped_ptr<ResourceProvider> child_resource_provider(
1163 ResourceProvider::Create(child_output_surface.get(),
1164 shared_bitmap_manager_.get(),
1165 gpu_memory_buffer_manager_.get(),
1166 NULL,
1168 false,
1169 1));
1171 gfx::Size size(1, 1);
1172 ResourceFormat format = RGBA_8888;
1173 size_t pixel_size = TextureSizeBytes(size, format);
1174 ASSERT_EQ(4U, pixel_size);
1176 ResourceProvider::ResourceId id1 = child_resource_provider->CreateResource(
1177 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
1178 uint8_t data1[4] = { 1, 2, 3, 4 };
1179 gfx::Rect rect(size);
1180 child_resource_provider->SetPixels(id1, data1, rect, rect, gfx::Vector2d());
1182 ReturnedResourceArray returned_to_child;
1183 int child_id =
1184 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1186 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1187 resource_ids_to_transfer.push_back(id1);
1188 TransferableResourceArray list;
1189 child_resource_provider->PrepareSendToParent(resource_ids_to_transfer,
1190 &list);
1191 ASSERT_EQ(1u, list.size());
1192 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
1193 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
1194 list[0].mailbox_holder.texture_target);
1195 EXPECT_TRUE(child_resource_provider->InUseByConsumer(id1));
1196 resource_provider_->ReceiveFromChild(child_id, list);
1199 EXPECT_EQ(0u, resource_provider_->num_resources());
1200 ASSERT_EQ(1u, returned_to_child.size());
1201 EXPECT_EQ(returned_to_child[0].id, id1);
1202 ResourceProvider::ResourceIdMap resource_map =
1203 resource_provider_->GetChildToParentMap(child_id);
1204 ResourceProvider::ResourceId mapped_id1 = resource_map[id1];
1205 EXPECT_EQ(0u, mapped_id1);
1207 resource_provider_->DestroyChild(child_id);
1208 EXPECT_EQ(0u, resource_provider_->num_resources());
1210 ASSERT_EQ(1u, returned_to_child.size());
1211 EXPECT_FALSE(returned_to_child[0].lost);
1214 TEST_P(ResourceProviderTest, TransferInvalidSoftware) {
1215 if (GetParam() != ResourceProvider::Bitmap)
1216 return;
1218 gfx::Size size(1, 1);
1219 ResourceFormat format = RGBA_8888;
1220 size_t pixel_size = TextureSizeBytes(size, format);
1221 ASSERT_EQ(4U, pixel_size);
1223 ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource(
1224 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
1225 uint8_t data1[4] = { 1, 2, 3, 4 };
1226 gfx::Rect rect(size);
1227 child_resource_provider_->SetPixels(id1, data1, rect, rect, gfx::Vector2d());
1229 ReturnedResourceArray returned_to_child;
1230 int child_id =
1231 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1233 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1234 resource_ids_to_transfer.push_back(id1);
1235 TransferableResourceArray list;
1236 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1237 &list);
1238 ASSERT_EQ(1u, list.size());
1239 // Make invalid.
1240 list[0].mailbox_holder.mailbox.name[1] = 5;
1241 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1242 resource_provider_->ReceiveFromChild(child_id, list);
1245 EXPECT_EQ(1u, resource_provider_->num_resources());
1246 EXPECT_EQ(0u, returned_to_child.size());
1248 ResourceProvider::ResourceIdMap resource_map =
1249 resource_provider_->GetChildToParentMap(child_id);
1250 ResourceProvider::ResourceId mapped_id1 = resource_map[id1];
1251 EXPECT_NE(0u, mapped_id1);
1253 ResourceProvider::ScopedReadLockSoftware lock(resource_provider_.get(),
1254 mapped_id1);
1255 EXPECT_FALSE(lock.valid());
1258 resource_provider_->DestroyChild(child_id);
1259 EXPECT_EQ(0u, resource_provider_->num_resources());
1261 ASSERT_EQ(1u, returned_to_child.size());
1262 EXPECT_FALSE(returned_to_child[0].lost);
1265 TEST_P(ResourceProviderTest, DeleteExportedResources) {
1266 gfx::Size size(1, 1);
1267 ResourceFormat format = RGBA_8888;
1268 size_t pixel_size = TextureSizeBytes(size, format);
1269 ASSERT_EQ(4U, pixel_size);
1271 ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource(
1272 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
1273 uint8_t data1[4] = { 1, 2, 3, 4 };
1274 gfx::Rect rect(size);
1275 child_resource_provider_->SetPixels(id1, data1, rect, rect, gfx::Vector2d());
1277 ResourceProvider::ResourceId id2 = child_resource_provider_->CreateResource(
1278 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
1279 uint8_t data2[4] = {5, 5, 5, 5};
1280 child_resource_provider_->SetPixels(id2, data2, rect, rect, gfx::Vector2d());
1282 ReturnedResourceArray returned_to_child;
1283 int child_id =
1284 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1286 // Transfer some resources to the parent.
1287 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1288 resource_ids_to_transfer.push_back(id1);
1289 resource_ids_to_transfer.push_back(id2);
1290 TransferableResourceArray list;
1291 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1292 &list);
1293 ASSERT_EQ(2u, list.size());
1294 if (GetParam() == ResourceProvider::GLTexture) {
1295 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
1296 EXPECT_NE(0u, list[1].mailbox_holder.sync_point);
1298 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1299 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
1300 resource_provider_->ReceiveFromChild(child_id, list);
1301 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1302 resource_ids_to_transfer);
1305 EXPECT_EQ(2u, resource_provider_->num_resources());
1306 ResourceProvider::ResourceIdMap resource_map =
1307 resource_provider_->GetChildToParentMap(child_id);
1308 ResourceProvider::ResourceId mapped_id1 = resource_map[id1];
1309 ResourceProvider::ResourceId mapped_id2 = resource_map[id2];
1310 EXPECT_NE(0u, mapped_id1);
1311 EXPECT_NE(0u, mapped_id2);
1312 EXPECT_FALSE(resource_provider_->InUseByConsumer(id1));
1313 EXPECT_FALSE(resource_provider_->InUseByConsumer(id2));
1316 // The parent transfers the resources to the grandparent.
1317 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1318 resource_ids_to_transfer.push_back(mapped_id1);
1319 resource_ids_to_transfer.push_back(mapped_id2);
1320 TransferableResourceArray list;
1321 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
1323 ASSERT_EQ(2u, list.size());
1324 if (GetParam() == ResourceProvider::GLTexture) {
1325 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
1326 EXPECT_NE(0u, list[1].mailbox_holder.sync_point);
1328 EXPECT_TRUE(resource_provider_->InUseByConsumer(id1));
1329 EXPECT_TRUE(resource_provider_->InUseByConsumer(id2));
1331 // Release the resource in the parent. Set no resources as being in use. The
1332 // resources are exported so that can't be transferred back yet.
1333 ResourceProvider::ResourceIdArray no_resources;
1334 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
1336 EXPECT_EQ(0u, returned_to_child.size());
1337 EXPECT_EQ(2u, resource_provider_->num_resources());
1339 // Return the resources from the grandparent to the parent. They should be
1340 // returned to the child then.
1341 EXPECT_EQ(2u, list.size());
1342 EXPECT_EQ(mapped_id1, list[0].id);
1343 EXPECT_EQ(mapped_id2, list[1].id);
1344 ReturnedResourceArray returned;
1345 TransferableResource::ReturnResources(list, &returned);
1346 resource_provider_->ReceiveReturnsFromParent(returned);
1348 EXPECT_EQ(0u, resource_provider_->num_resources());
1349 ASSERT_EQ(2u, returned_to_child.size());
1350 if (GetParam() == ResourceProvider::GLTexture) {
1351 EXPECT_NE(0u, returned_to_child[0].sync_point);
1352 EXPECT_NE(0u, returned_to_child[1].sync_point);
1354 EXPECT_FALSE(returned_to_child[0].lost);
1355 EXPECT_FALSE(returned_to_child[1].lost);
1359 TEST_P(ResourceProviderTest, DestroyChildWithExportedResources) {
1360 gfx::Size size(1, 1);
1361 ResourceFormat format = RGBA_8888;
1362 size_t pixel_size = TextureSizeBytes(size, format);
1363 ASSERT_EQ(4U, pixel_size);
1365 ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource(
1366 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
1367 uint8_t data1[4] = {1, 2, 3, 4};
1368 gfx::Rect rect(size);
1369 child_resource_provider_->SetPixels(id1, data1, rect, rect, gfx::Vector2d());
1371 ResourceProvider::ResourceId id2 = child_resource_provider_->CreateResource(
1372 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
1373 uint8_t data2[4] = {5, 5, 5, 5};
1374 child_resource_provider_->SetPixels(id2, data2, rect, rect, gfx::Vector2d());
1376 ReturnedResourceArray returned_to_child;
1377 int child_id =
1378 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1380 // Transfer some resources to the parent.
1381 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1382 resource_ids_to_transfer.push_back(id1);
1383 resource_ids_to_transfer.push_back(id2);
1384 TransferableResourceArray list;
1385 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1386 &list);
1387 ASSERT_EQ(2u, list.size());
1388 if (GetParam() == ResourceProvider::GLTexture) {
1389 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
1390 EXPECT_NE(0u, list[1].mailbox_holder.sync_point);
1392 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1393 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
1394 resource_provider_->ReceiveFromChild(child_id, list);
1395 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1396 resource_ids_to_transfer);
1399 EXPECT_EQ(2u, resource_provider_->num_resources());
1400 ResourceProvider::ResourceIdMap resource_map =
1401 resource_provider_->GetChildToParentMap(child_id);
1402 ResourceProvider::ResourceId mapped_id1 = resource_map[id1];
1403 ResourceProvider::ResourceId mapped_id2 = resource_map[id2];
1404 EXPECT_NE(0u, mapped_id1);
1405 EXPECT_NE(0u, mapped_id2);
1406 EXPECT_FALSE(resource_provider_->InUseByConsumer(id1));
1407 EXPECT_FALSE(resource_provider_->InUseByConsumer(id2));
1410 // The parent transfers the resources to the grandparent.
1411 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1412 resource_ids_to_transfer.push_back(mapped_id1);
1413 resource_ids_to_transfer.push_back(mapped_id2);
1414 TransferableResourceArray list;
1415 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
1417 ASSERT_EQ(2u, list.size());
1418 if (GetParam() == ResourceProvider::GLTexture) {
1419 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
1420 EXPECT_NE(0u, list[1].mailbox_holder.sync_point);
1422 EXPECT_TRUE(resource_provider_->InUseByConsumer(id1));
1423 EXPECT_TRUE(resource_provider_->InUseByConsumer(id2));
1425 // Release the resource in the parent. Set no resources as being in use. The
1426 // resources are exported so that can't be transferred back yet.
1427 ResourceProvider::ResourceIdArray no_resources;
1428 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
1430 // Destroy the child, the resources should not be returned yet.
1431 EXPECT_EQ(0u, returned_to_child.size());
1432 EXPECT_EQ(2u, resource_provider_->num_resources());
1434 resource_provider_->DestroyChild(child_id);
1436 EXPECT_EQ(2u, resource_provider_->num_resources());
1437 ASSERT_EQ(0u, returned_to_child.size());
1439 // Return a resource from the grandparent, it should be returned at this
1440 // point.
1441 EXPECT_EQ(2u, list.size());
1442 EXPECT_EQ(mapped_id1, list[0].id);
1443 EXPECT_EQ(mapped_id2, list[1].id);
1444 TransferableResourceArray return_list;
1445 return_list.push_back(list[1]);
1446 list.pop_back();
1447 ReturnedResourceArray returned;
1448 TransferableResource::ReturnResources(return_list, &returned);
1449 resource_provider_->ReceiveReturnsFromParent(returned);
1451 EXPECT_EQ(1u, resource_provider_->num_resources());
1452 ASSERT_EQ(1u, returned_to_child.size());
1453 if (GetParam() == ResourceProvider::GLTexture) {
1454 EXPECT_NE(0u, returned_to_child[0].sync_point);
1456 EXPECT_FALSE(returned_to_child[0].lost);
1457 returned_to_child.clear();
1459 // Destroy the parent resource provider. The resource that's left should be
1460 // lost at this point, and returned.
1461 resource_provider_ = nullptr;
1462 ASSERT_EQ(1u, returned_to_child.size());
1463 if (GetParam() == ResourceProvider::GLTexture) {
1464 EXPECT_NE(0u, returned_to_child[0].sync_point);
1466 EXPECT_TRUE(returned_to_child[0].lost);
1470 TEST_P(ResourceProviderTest, DeleteTransferredResources) {
1471 gfx::Size size(1, 1);
1472 ResourceFormat format = RGBA_8888;
1473 size_t pixel_size = TextureSizeBytes(size, format);
1474 ASSERT_EQ(4U, pixel_size);
1476 ResourceProvider::ResourceId id = child_resource_provider_->CreateResource(
1477 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
1478 uint8_t data[4] = { 1, 2, 3, 4 };
1479 gfx::Rect rect(size);
1480 child_resource_provider_->SetPixels(id, data, rect, rect, gfx::Vector2d());
1482 ReturnedResourceArray returned_to_child;
1483 int child_id =
1484 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1486 // Transfer some resource to the parent.
1487 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1488 resource_ids_to_transfer.push_back(id);
1489 TransferableResourceArray list;
1490 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1491 &list);
1492 ASSERT_EQ(1u, list.size());
1493 if (GetParam() == ResourceProvider::GLTexture)
1494 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
1495 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id));
1496 resource_provider_->ReceiveFromChild(child_id, list);
1497 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1498 resource_ids_to_transfer);
1501 // Delete textures in the child, while they are transfered.
1502 child_resource_provider_->DeleteResource(id);
1503 EXPECT_EQ(1u, child_resource_provider_->num_resources());
1505 EXPECT_EQ(0u, returned_to_child.size());
1507 // Transfer resources back from the parent to the child. Set no resources as
1508 // being in use.
1509 ResourceProvider::ResourceIdArray no_resources;
1510 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
1512 ASSERT_EQ(1u, returned_to_child.size());
1513 if (GetParam() == ResourceProvider::GLTexture)
1514 EXPECT_NE(0u, returned_to_child[0].sync_point);
1515 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
1517 EXPECT_EQ(0u, child_resource_provider_->num_resources());
1520 TEST_P(ResourceProviderTest, UnuseTransferredResources) {
1521 gfx::Size size(1, 1);
1522 ResourceFormat format = RGBA_8888;
1523 size_t pixel_size = TextureSizeBytes(size, format);
1524 ASSERT_EQ(4U, pixel_size);
1526 ResourceProvider::ResourceId id = child_resource_provider_->CreateResource(
1527 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
1528 uint8_t data[4] = {1, 2, 3, 4};
1529 gfx::Rect rect(size);
1530 child_resource_provider_->SetPixels(id, data, rect, rect, gfx::Vector2d());
1532 ReturnedResourceArray returned_to_child;
1533 int child_id =
1534 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1535 const ResourceProvider::ResourceIdMap& map =
1536 resource_provider_->GetChildToParentMap(child_id);
1538 // Transfer some resource to the parent.
1539 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1540 resource_ids_to_transfer.push_back(id);
1541 TransferableResourceArray list;
1542 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1543 &list);
1544 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id));
1545 resource_provider_->ReceiveFromChild(child_id, list);
1546 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1547 resource_ids_to_transfer);
1549 TransferableResourceArray sent_to_top_level;
1551 // Parent transfers to top-level.
1552 ASSERT_TRUE(map.find(id) != map.end());
1553 ResourceProvider::ResourceId parent_id = map.find(id)->second;
1554 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1555 resource_ids_to_transfer.push_back(parent_id);
1556 resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1557 &sent_to_top_level);
1558 EXPECT_TRUE(resource_provider_->InUseByConsumer(parent_id));
1561 // Stop using resource.
1562 ResourceProvider::ResourceIdArray empty;
1563 resource_provider_->DeclareUsedResourcesFromChild(child_id, empty);
1564 // Resource is not yet returned to the child, since it's in use by the
1565 // top-level.
1566 EXPECT_TRUE(returned_to_child.empty());
1569 // Send the resource to the parent again.
1570 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1571 resource_ids_to_transfer.push_back(id);
1572 TransferableResourceArray list;
1573 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1574 &list);
1575 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id));
1576 resource_provider_->ReceiveFromChild(child_id, list);
1577 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1578 resource_ids_to_transfer);
1581 // Receive returns back from top-level.
1582 ReturnedResourceArray returned;
1583 TransferableResource::ReturnResources(sent_to_top_level, &returned);
1584 resource_provider_->ReceiveReturnsFromParent(returned);
1585 // Resource is still not yet returned to the child, since it's declared used
1586 // in the parent.
1587 EXPECT_TRUE(returned_to_child.empty());
1588 ASSERT_TRUE(map.find(id) != map.end());
1589 ResourceProvider::ResourceId parent_id = map.find(id)->second;
1590 EXPECT_FALSE(resource_provider_->InUseByConsumer(parent_id));
1593 sent_to_top_level.clear();
1594 // Parent transfers again to top-level.
1595 ASSERT_TRUE(map.find(id) != map.end());
1596 ResourceProvider::ResourceId parent_id = map.find(id)->second;
1597 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1598 resource_ids_to_transfer.push_back(parent_id);
1599 resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1600 &sent_to_top_level);
1601 EXPECT_TRUE(resource_provider_->InUseByConsumer(parent_id));
1604 // Receive returns back from top-level.
1605 ReturnedResourceArray returned;
1606 TransferableResource::ReturnResources(sent_to_top_level, &returned);
1607 resource_provider_->ReceiveReturnsFromParent(returned);
1608 // Resource is still not yet returned to the child, since it's still
1609 // declared used in the parent.
1610 EXPECT_TRUE(returned_to_child.empty());
1611 ASSERT_TRUE(map.find(id) != map.end());
1612 ResourceProvider::ResourceId parent_id = map.find(id)->second;
1613 EXPECT_FALSE(resource_provider_->InUseByConsumer(parent_id));
1616 // Stop using resource.
1617 ResourceProvider::ResourceIdArray empty;
1618 resource_provider_->DeclareUsedResourcesFromChild(child_id, empty);
1619 // Resource should have been returned to the child, since it's no longer in
1620 // use by the top-level.
1621 ASSERT_EQ(1u, returned_to_child.size());
1622 EXPECT_EQ(id, returned_to_child[0].id);
1623 EXPECT_EQ(2, returned_to_child[0].count);
1624 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
1625 returned_to_child.clear();
1626 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id));
1630 class ResourceProviderTestTextureFilters : public ResourceProviderTest {
1631 public:
1632 static void RunTest(GLenum child_filter, GLenum parent_filter) {
1633 scoped_ptr<TextureStateTrackingContext> child_context_owned(
1634 new TextureStateTrackingContext);
1635 TextureStateTrackingContext* child_context = child_context_owned.get();
1637 FakeOutputSurfaceClient child_output_surface_client;
1638 scoped_ptr<OutputSurface> child_output_surface(
1639 FakeOutputSurface::Create3d(child_context_owned.Pass()));
1640 CHECK(child_output_surface->BindToClient(&child_output_surface_client));
1641 scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
1642 new TestSharedBitmapManager());
1644 scoped_ptr<ResourceProvider> child_resource_provider(
1645 ResourceProvider::Create(child_output_surface.get(),
1646 shared_bitmap_manager.get(),
1647 NULL,
1648 NULL,
1650 false,
1651 1));
1653 scoped_ptr<TextureStateTrackingContext> parent_context_owned(
1654 new TextureStateTrackingContext);
1655 TextureStateTrackingContext* parent_context = parent_context_owned.get();
1657 FakeOutputSurfaceClient parent_output_surface_client;
1658 scoped_ptr<OutputSurface> parent_output_surface(
1659 FakeOutputSurface::Create3d(parent_context_owned.Pass()));
1660 CHECK(parent_output_surface->BindToClient(&parent_output_surface_client));
1662 scoped_ptr<ResourceProvider> parent_resource_provider(
1663 ResourceProvider::Create(parent_output_surface.get(),
1664 shared_bitmap_manager.get(),
1665 NULL,
1666 NULL,
1668 false,
1669 1));
1671 gfx::Size size(1, 1);
1672 ResourceFormat format = RGBA_8888;
1673 int child_texture_id = 1;
1674 int parent_texture_id = 2;
1676 size_t pixel_size = TextureSizeBytes(size, format);
1677 ASSERT_EQ(4U, pixel_size);
1679 ResourceProvider::ResourceId id = child_resource_provider->CreateResource(
1680 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
1682 // The new texture is created with GL_LINEAR.
1683 EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, child_texture_id))
1684 .Times(2); // Once to create and once to allocate.
1685 EXPECT_CALL(*child_context,
1686 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
1687 EXPECT_CALL(*child_context,
1688 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
1689 EXPECT_CALL(
1690 *child_context,
1691 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
1692 EXPECT_CALL(
1693 *child_context,
1694 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
1695 EXPECT_CALL(*child_context,
1696 texParameteri(GL_TEXTURE_2D,
1697 GL_TEXTURE_POOL_CHROMIUM,
1698 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM));
1699 child_resource_provider->AllocateForTesting(id);
1700 Mock::VerifyAndClearExpectations(child_context);
1702 uint8_t data[4] = { 1, 2, 3, 4 };
1703 gfx::Rect rect(size);
1705 EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, child_texture_id));
1706 child_resource_provider->SetPixels(id, data, rect, rect, gfx::Vector2d());
1707 Mock::VerifyAndClearExpectations(child_context);
1709 // The texture is set to |child_filter| in the child.
1710 EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, child_texture_id));
1711 if (child_filter != GL_LINEAR) {
1712 EXPECT_CALL(
1713 *child_context,
1714 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, child_filter));
1715 EXPECT_CALL(
1716 *child_context,
1717 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, child_filter));
1719 SetResourceFilter(child_resource_provider.get(), id, child_filter);
1720 Mock::VerifyAndClearExpectations(child_context);
1722 ReturnedResourceArray returned_to_child;
1723 int child_id = parent_resource_provider->CreateChild(
1724 GetReturnCallback(&returned_to_child));
1726 // Transfer some resource to the parent.
1727 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1728 resource_ids_to_transfer.push_back(id);
1729 TransferableResourceArray list;
1731 EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, child_texture_id));
1732 EXPECT_CALL(*child_context,
1733 produceTextureCHROMIUM(GL_TEXTURE_2D, _));
1734 EXPECT_CALL(*child_context, insertSyncPoint());
1735 child_resource_provider->PrepareSendToParent(resource_ids_to_transfer,
1736 &list);
1737 Mock::VerifyAndClearExpectations(child_context);
1739 ASSERT_EQ(1u, list.size());
1740 EXPECT_EQ(static_cast<unsigned>(child_filter), list[0].filter);
1742 EXPECT_CALL(*parent_context,
1743 bindTexture(GL_TEXTURE_2D, parent_texture_id));
1744 EXPECT_CALL(*parent_context, consumeTextureCHROMIUM(GL_TEXTURE_2D, _));
1745 parent_resource_provider->ReceiveFromChild(child_id, list);
1747 parent_resource_provider->WaitSyncPointIfNeeded(list[0].id);
1748 ResourceProvider::ScopedReadLockGL lock(parent_resource_provider.get(),
1749 list[0].id);
1751 Mock::VerifyAndClearExpectations(parent_context);
1753 parent_resource_provider->DeclareUsedResourcesFromChild(
1754 child_id, resource_ids_to_transfer);
1755 Mock::VerifyAndClearExpectations(parent_context);
1757 ResourceProvider::ResourceIdMap resource_map =
1758 parent_resource_provider->GetChildToParentMap(child_id);
1759 ResourceProvider::ResourceId mapped_id = resource_map[id];
1760 EXPECT_NE(0u, mapped_id);
1762 // The texture is set to |parent_filter| in the parent.
1763 EXPECT_CALL(*parent_context, bindTexture(GL_TEXTURE_2D, parent_texture_id));
1764 EXPECT_CALL(
1765 *parent_context,
1766 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, parent_filter));
1767 EXPECT_CALL(
1768 *parent_context,
1769 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, parent_filter));
1770 SetResourceFilter(parent_resource_provider.get(), mapped_id, parent_filter);
1771 Mock::VerifyAndClearExpectations(parent_context);
1773 // The texture should be reset to |child_filter| in the parent when it is
1774 // returned, since that is how it was received.
1775 EXPECT_CALL(*parent_context, bindTexture(GL_TEXTURE_2D, parent_texture_id));
1776 EXPECT_CALL(
1777 *parent_context,
1778 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, child_filter));
1779 EXPECT_CALL(
1780 *parent_context,
1781 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, child_filter));
1784 EXPECT_EQ(0u, returned_to_child.size());
1786 // Transfer resources back from the parent to the child. Set no resources
1787 // as being in use.
1788 ResourceProvider::ResourceIdArray no_resources;
1789 EXPECT_CALL(*parent_context, insertSyncPoint());
1790 parent_resource_provider->DeclareUsedResourcesFromChild(child_id,
1791 no_resources);
1792 Mock::VerifyAndClearExpectations(parent_context);
1794 ASSERT_EQ(1u, returned_to_child.size());
1795 child_resource_provider->ReceiveReturnsFromParent(returned_to_child);
1798 // The child remembers the texture filter is set to |child_filter|.
1799 EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, child_texture_id));
1800 SetResourceFilter(child_resource_provider.get(), id, child_filter);
1801 Mock::VerifyAndClearExpectations(child_context);
1805 TEST_P(ResourceProviderTest, TextureFilters_ChildNearestParentLinear) {
1806 if (GetParam() != ResourceProvider::GLTexture)
1807 return;
1808 ResourceProviderTestTextureFilters::RunTest(GL_NEAREST, GL_LINEAR);
1811 TEST_P(ResourceProviderTest, TextureFilters_ChildLinearParentNearest) {
1812 if (GetParam() != ResourceProvider::GLTexture)
1813 return;
1814 ResourceProviderTestTextureFilters::RunTest(GL_LINEAR, GL_NEAREST);
1817 TEST_P(ResourceProviderTest, TransferMailboxResources) {
1818 // Other mailbox transfers tested elsewhere.
1819 if (GetParam() != ResourceProvider::GLTexture)
1820 return;
1821 unsigned texture = context()->createTexture();
1822 context()->bindTexture(GL_TEXTURE_2D, texture);
1823 uint8_t data[4] = { 1, 2, 3, 4 };
1824 context()->texImage2D(
1825 GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &data);
1826 gpu::Mailbox mailbox;
1827 context()->genMailboxCHROMIUM(mailbox.name);
1828 context()->produceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
1829 uint32 sync_point = context()->insertSyncPoint();
1831 // All the logic below assumes that the sync points are all positive.
1832 EXPECT_LT(0u, sync_point);
1834 uint32 release_sync_point = 0;
1835 bool lost_resource = false;
1836 BlockingTaskRunner* main_thread_task_runner = NULL;
1837 ReleaseCallbackImpl callback = base::Bind(ReleaseCallback,
1838 &release_sync_point,
1839 &lost_resource,
1840 &main_thread_task_runner);
1841 ResourceProvider::ResourceId resource =
1842 resource_provider_->CreateResourceFromTextureMailbox(
1843 TextureMailbox(mailbox, GL_TEXTURE_2D, sync_point),
1844 SingleReleaseCallbackImpl::Create(callback));
1845 EXPECT_EQ(1u, context()->NumTextures());
1846 EXPECT_EQ(0u, release_sync_point);
1848 // Transfer the resource, expect the sync points to be consistent.
1849 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1850 resource_ids_to_transfer.push_back(resource);
1851 TransferableResourceArray list;
1852 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
1853 ASSERT_EQ(1u, list.size());
1854 EXPECT_LE(sync_point, list[0].mailbox_holder.sync_point);
1855 EXPECT_EQ(0,
1856 memcmp(mailbox.name,
1857 list[0].mailbox_holder.mailbox.name,
1858 sizeof(mailbox.name)));
1859 EXPECT_EQ(0u, release_sync_point);
1861 context()->waitSyncPoint(list[0].mailbox_holder.sync_point);
1862 unsigned other_texture = context()->createTexture();
1863 context()->bindTexture(GL_TEXTURE_2D, other_texture);
1864 context()->consumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
1865 uint8_t test_data[4] = { 0 };
1866 context()->GetPixels(
1867 gfx::Size(1, 1), RGBA_8888, test_data);
1868 EXPECT_EQ(0, memcmp(data, test_data, sizeof(data)));
1869 context()->produceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
1870 context()->deleteTexture(other_texture);
1871 list[0].mailbox_holder.sync_point = context()->insertSyncPoint();
1872 EXPECT_LT(0u, list[0].mailbox_holder.sync_point);
1874 // Receive the resource, then delete it, expect the sync points to be
1875 // consistent.
1876 ReturnedResourceArray returned;
1877 TransferableResource::ReturnResources(list, &returned);
1878 resource_provider_->ReceiveReturnsFromParent(returned);
1879 EXPECT_EQ(1u, context()->NumTextures());
1880 EXPECT_EQ(0u, release_sync_point);
1882 resource_provider_->DeleteResource(resource);
1883 EXPECT_LE(list[0].mailbox_holder.sync_point, release_sync_point);
1884 EXPECT_FALSE(lost_resource);
1885 EXPECT_EQ(main_thread_task_runner_.get(), main_thread_task_runner);
1888 // We're going to do the same thing as above, but testing the case where we
1889 // delete the resource before we receive it back.
1890 sync_point = release_sync_point;
1891 EXPECT_LT(0u, sync_point);
1892 release_sync_point = 0;
1893 resource = resource_provider_->CreateResourceFromTextureMailbox(
1894 TextureMailbox(mailbox, GL_TEXTURE_2D, sync_point),
1895 SingleReleaseCallbackImpl::Create(callback));
1896 EXPECT_EQ(1u, context()->NumTextures());
1897 EXPECT_EQ(0u, release_sync_point);
1899 // Transfer the resource, expect the sync points to be consistent.
1900 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1901 resource_ids_to_transfer.push_back(resource);
1902 TransferableResourceArray list;
1903 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
1904 ASSERT_EQ(1u, list.size());
1905 EXPECT_LE(sync_point, list[0].mailbox_holder.sync_point);
1906 EXPECT_EQ(0,
1907 memcmp(mailbox.name,
1908 list[0].mailbox_holder.mailbox.name,
1909 sizeof(mailbox.name)));
1910 EXPECT_EQ(0u, release_sync_point);
1912 context()->waitSyncPoint(list[0].mailbox_holder.sync_point);
1913 unsigned other_texture = context()->createTexture();
1914 context()->bindTexture(GL_TEXTURE_2D, other_texture);
1915 context()->consumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
1916 uint8_t test_data[4] = { 0 };
1917 context()->GetPixels(
1918 gfx::Size(1, 1), RGBA_8888, test_data);
1919 EXPECT_EQ(0, memcmp(data, test_data, sizeof(data)));
1920 context()->produceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
1921 context()->deleteTexture(other_texture);
1922 list[0].mailbox_holder.sync_point = context()->insertSyncPoint();
1923 EXPECT_LT(0u, list[0].mailbox_holder.sync_point);
1925 // Delete the resource, which shouldn't do anything.
1926 resource_provider_->DeleteResource(resource);
1927 EXPECT_EQ(1u, context()->NumTextures());
1928 EXPECT_EQ(0u, release_sync_point);
1930 // Then receive the resource which should release the mailbox, expect the
1931 // sync points to be consistent.
1932 ReturnedResourceArray returned;
1933 TransferableResource::ReturnResources(list, &returned);
1934 resource_provider_->ReceiveReturnsFromParent(returned);
1935 EXPECT_LE(list[0].mailbox_holder.sync_point, release_sync_point);
1936 EXPECT_FALSE(lost_resource);
1937 EXPECT_EQ(main_thread_task_runner_.get(), main_thread_task_runner);
1940 context()->waitSyncPoint(release_sync_point);
1941 context()->bindTexture(GL_TEXTURE_2D, texture);
1942 context()->consumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
1943 context()->deleteTexture(texture);
1946 TEST_P(ResourceProviderTest, LostResourceInParent) {
1947 gfx::Size size(1, 1);
1948 ResourceFormat format = RGBA_8888;
1949 ResourceProvider::ResourceId resource =
1950 child_resource_provider_->CreateResource(
1951 size,
1952 GL_CLAMP_TO_EDGE,
1953 ResourceProvider::TextureHintImmutable,
1954 format);
1955 child_resource_provider_->AllocateForTesting(resource);
1956 // Expect a GL resource to be lost.
1957 bool should_lose_resource = GetParam() == ResourceProvider::GLTexture;
1959 ReturnedResourceArray returned_to_child;
1960 int child_id =
1961 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1963 // Transfer the resource to the parent.
1964 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1965 resource_ids_to_transfer.push_back(resource);
1966 TransferableResourceArray list;
1967 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1968 &list);
1969 EXPECT_EQ(1u, list.size());
1971 resource_provider_->ReceiveFromChild(child_id, list);
1972 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1973 resource_ids_to_transfer);
1976 // Lose the output surface in the parent.
1977 resource_provider_->DidLoseOutputSurface();
1980 EXPECT_EQ(0u, returned_to_child.size());
1982 // Transfer resources back from the parent to the child. Set no resources as
1983 // being in use.
1984 ResourceProvider::ResourceIdArray no_resources;
1985 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
1987 // Expect a GL resource to be lost.
1988 ASSERT_EQ(1u, returned_to_child.size());
1989 EXPECT_EQ(should_lose_resource, returned_to_child[0].lost);
1990 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
1991 returned_to_child.clear();
1994 // A GL resource should be lost.
1995 EXPECT_EQ(should_lose_resource, child_resource_provider_->IsLost(resource));
1997 // Lost resources stay in use in the parent forever.
1998 EXPECT_EQ(should_lose_resource,
1999 child_resource_provider_->InUseByConsumer(resource));
2002 TEST_P(ResourceProviderTest, LostResourceInGrandParent) {
2003 gfx::Size size(1, 1);
2004 ResourceFormat format = RGBA_8888;
2005 ResourceProvider::ResourceId resource =
2006 child_resource_provider_->CreateResource(
2007 size,
2008 GL_CLAMP_TO_EDGE,
2009 ResourceProvider::TextureHintImmutable,
2010 format);
2011 child_resource_provider_->AllocateForTesting(resource);
2013 ReturnedResourceArray returned_to_child;
2014 int child_id =
2015 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
2017 // Transfer the resource to the parent.
2018 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2019 resource_ids_to_transfer.push_back(resource);
2020 TransferableResourceArray list;
2021 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
2022 &list);
2023 EXPECT_EQ(1u, list.size());
2025 resource_provider_->ReceiveFromChild(child_id, list);
2026 resource_provider_->DeclareUsedResourcesFromChild(child_id,
2027 resource_ids_to_transfer);
2031 ResourceProvider::ResourceIdMap resource_map =
2032 resource_provider_->GetChildToParentMap(child_id);
2033 ResourceProvider::ResourceId parent_resource = resource_map[resource];
2034 EXPECT_NE(0u, parent_resource);
2036 // Transfer to a grandparent.
2037 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2038 resource_ids_to_transfer.push_back(parent_resource);
2039 TransferableResourceArray list;
2040 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
2042 // Receive back a lost resource from the grandparent.
2043 EXPECT_EQ(1u, list.size());
2044 EXPECT_EQ(parent_resource, list[0].id);
2045 ReturnedResourceArray returned;
2046 TransferableResource::ReturnResources(list, &returned);
2047 EXPECT_EQ(1u, returned.size());
2048 EXPECT_EQ(parent_resource, returned[0].id);
2049 returned[0].lost = true;
2050 resource_provider_->ReceiveReturnsFromParent(returned);
2052 // The resource should be lost.
2053 EXPECT_TRUE(resource_provider_->IsLost(parent_resource));
2055 // Lost resources stay in use in the parent forever.
2056 EXPECT_TRUE(resource_provider_->InUseByConsumer(parent_resource));
2060 EXPECT_EQ(0u, returned_to_child.size());
2062 // Transfer resources back from the parent to the child. Set no resources as
2063 // being in use.
2064 ResourceProvider::ResourceIdArray no_resources;
2065 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
2067 // Expect the resource to be lost.
2068 ASSERT_EQ(1u, returned_to_child.size());
2069 EXPECT_TRUE(returned_to_child[0].lost);
2070 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
2071 returned_to_child.clear();
2074 // The resource should be lost.
2075 EXPECT_TRUE(child_resource_provider_->IsLost(resource));
2077 // Lost resources stay in use in the parent forever.
2078 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(resource));
2081 TEST_P(ResourceProviderTest, LostMailboxInParent) {
2082 uint32 release_sync_point = 0;
2083 bool lost_resource = false;
2084 bool release_called = false;
2085 uint32 sync_point = 0;
2086 ResourceProvider::ResourceId resource = CreateChildMailbox(
2087 &release_sync_point, &lost_resource, &release_called, &sync_point);
2089 ReturnedResourceArray returned_to_child;
2090 int child_id =
2091 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
2093 // Transfer the resource to the parent.
2094 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2095 resource_ids_to_transfer.push_back(resource);
2096 TransferableResourceArray list;
2097 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
2098 &list);
2099 EXPECT_EQ(1u, list.size());
2101 resource_provider_->ReceiveFromChild(child_id, list);
2102 resource_provider_->DeclareUsedResourcesFromChild(child_id,
2103 resource_ids_to_transfer);
2106 // Lose the output surface in the parent.
2107 resource_provider_->DidLoseOutputSurface();
2110 EXPECT_EQ(0u, returned_to_child.size());
2112 // Transfer resources back from the parent to the child. Set no resources as
2113 // being in use.
2114 ResourceProvider::ResourceIdArray no_resources;
2115 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
2117 ASSERT_EQ(1u, returned_to_child.size());
2118 // Losing an output surface only loses hardware resources.
2119 EXPECT_EQ(returned_to_child[0].lost,
2120 GetParam() == ResourceProvider::GLTexture);
2121 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
2122 returned_to_child.clear();
2125 // Delete the resource in the child. Expect the resource to be lost if it's
2126 // a GL texture.
2127 child_resource_provider_->DeleteResource(resource);
2128 EXPECT_EQ(lost_resource, GetParam() == ResourceProvider::GLTexture);
2131 TEST_P(ResourceProviderTest, LostMailboxInGrandParent) {
2132 uint32 release_sync_point = 0;
2133 bool lost_resource = false;
2134 bool release_called = false;
2135 uint32 sync_point = 0;
2136 ResourceProvider::ResourceId resource = CreateChildMailbox(
2137 &release_sync_point, &lost_resource, &release_called, &sync_point);
2139 ReturnedResourceArray returned_to_child;
2140 int child_id =
2141 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
2143 // Transfer the resource to the parent.
2144 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2145 resource_ids_to_transfer.push_back(resource);
2146 TransferableResourceArray list;
2147 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
2148 &list);
2149 EXPECT_EQ(1u, list.size());
2151 resource_provider_->ReceiveFromChild(child_id, list);
2152 resource_provider_->DeclareUsedResourcesFromChild(child_id,
2153 resource_ids_to_transfer);
2157 ResourceProvider::ResourceIdMap resource_map =
2158 resource_provider_->GetChildToParentMap(child_id);
2159 ResourceProvider::ResourceId parent_resource = resource_map[resource];
2160 EXPECT_NE(0u, parent_resource);
2162 // Transfer to a grandparent.
2163 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2164 resource_ids_to_transfer.push_back(parent_resource);
2165 TransferableResourceArray list;
2166 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
2168 // Receive back a lost resource from the grandparent.
2169 EXPECT_EQ(1u, list.size());
2170 EXPECT_EQ(parent_resource, list[0].id);
2171 ReturnedResourceArray returned;
2172 TransferableResource::ReturnResources(list, &returned);
2173 EXPECT_EQ(1u, returned.size());
2174 EXPECT_EQ(parent_resource, returned[0].id);
2175 returned[0].lost = true;
2176 resource_provider_->ReceiveReturnsFromParent(returned);
2180 EXPECT_EQ(0u, returned_to_child.size());
2182 // Transfer resources back from the parent to the child. Set no resources as
2183 // being in use.
2184 ResourceProvider::ResourceIdArray no_resources;
2185 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
2187 // Expect the resource to be lost.
2188 ASSERT_EQ(1u, returned_to_child.size());
2189 EXPECT_TRUE(returned_to_child[0].lost);
2190 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
2191 returned_to_child.clear();
2194 // Delete the resource in the child. Expect the resource to be lost.
2195 child_resource_provider_->DeleteResource(resource);
2196 EXPECT_TRUE(lost_resource);
2199 TEST_P(ResourceProviderTest, Shutdown) {
2200 uint32 release_sync_point = 0;
2201 bool lost_resource = false;
2202 bool release_called = false;
2203 uint32 sync_point = 0;
2204 CreateChildMailbox(
2205 &release_sync_point, &lost_resource, &release_called, &sync_point);
2207 EXPECT_EQ(0u, release_sync_point);
2208 EXPECT_FALSE(lost_resource);
2210 child_resource_provider_ = nullptr;
2212 if (GetParam() == ResourceProvider::GLTexture) {
2213 EXPECT_LE(sync_point, release_sync_point);
2215 EXPECT_TRUE(release_called);
2216 EXPECT_FALSE(lost_resource);
2219 TEST_P(ResourceProviderTest, ShutdownWithExportedResource) {
2220 uint32 release_sync_point = 0;
2221 bool lost_resource = false;
2222 bool release_called = false;
2223 uint32 sync_point = 0;
2224 ResourceProvider::ResourceId resource = CreateChildMailbox(
2225 &release_sync_point, &lost_resource, &release_called, &sync_point);
2227 // Transfer the resource, so we can't release it properly on shutdown.
2228 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2229 resource_ids_to_transfer.push_back(resource);
2230 TransferableResourceArray list;
2231 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
2232 &list);
2234 EXPECT_EQ(0u, release_sync_point);
2235 EXPECT_FALSE(lost_resource);
2237 child_resource_provider_ = nullptr;
2239 // Since the resource is in the parent, the child considers it lost.
2240 EXPECT_EQ(0u, release_sync_point);
2241 EXPECT_TRUE(lost_resource);
2244 TEST_P(ResourceProviderTest, LostContext) {
2245 // TextureMailbox callbacks only exist for GL textures for now.
2246 if (GetParam() != ResourceProvider::GLTexture)
2247 return;
2248 unsigned texture = context()->createTexture();
2249 context()->bindTexture(GL_TEXTURE_2D, texture);
2250 gpu::Mailbox mailbox;
2251 context()->genMailboxCHROMIUM(mailbox.name);
2252 context()->produceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
2253 uint32 sync_point = context()->insertSyncPoint();
2255 EXPECT_LT(0u, sync_point);
2257 uint32 release_sync_point = 0;
2258 bool lost_resource = false;
2259 BlockingTaskRunner* main_thread_task_runner = NULL;
2260 scoped_ptr<SingleReleaseCallbackImpl> callback =
2261 SingleReleaseCallbackImpl::Create(base::Bind(ReleaseCallback,
2262 &release_sync_point,
2263 &lost_resource,
2264 &main_thread_task_runner));
2265 resource_provider_->CreateResourceFromTextureMailbox(
2266 TextureMailbox(mailbox, GL_TEXTURE_2D, sync_point), callback.Pass());
2268 EXPECT_EQ(0u, release_sync_point);
2269 EXPECT_FALSE(lost_resource);
2270 EXPECT_EQ(NULL, main_thread_task_runner);
2272 resource_provider_->DidLoseOutputSurface();
2273 resource_provider_ = nullptr;
2275 EXPECT_LE(sync_point, release_sync_point);
2276 EXPECT_TRUE(lost_resource);
2277 EXPECT_EQ(main_thread_task_runner_.get(), main_thread_task_runner);
2280 TEST_P(ResourceProviderTest, ScopedSampler) {
2281 // Sampling is only supported for GL textures.
2282 if (GetParam() != ResourceProvider::GLTexture)
2283 return;
2285 scoped_ptr<TextureStateTrackingContext> context_owned(
2286 new TextureStateTrackingContext);
2287 TextureStateTrackingContext* context = context_owned.get();
2289 FakeOutputSurfaceClient output_surface_client;
2290 scoped_ptr<OutputSurface> output_surface(
2291 FakeOutputSurface::Create3d(context_owned.Pass()));
2292 CHECK(output_surface->BindToClient(&output_surface_client));
2294 scoped_ptr<ResourceProvider> resource_provider(
2295 ResourceProvider::Create(output_surface.get(),
2296 shared_bitmap_manager_.get(),
2297 gpu_memory_buffer_manager_.get(),
2298 NULL,
2300 false,
2301 1));
2303 gfx::Size size(1, 1);
2304 ResourceFormat format = RGBA_8888;
2305 int texture_id = 1;
2307 ResourceProvider::ResourceId id = resource_provider->CreateResource(
2308 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
2310 // Check that the texture gets created with the right sampler settings.
2311 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id))
2312 .Times(2); // Once to create and once to allocate.
2313 EXPECT_CALL(*context,
2314 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
2315 EXPECT_CALL(*context,
2316 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
2317 EXPECT_CALL(
2318 *context,
2319 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
2320 EXPECT_CALL(
2321 *context,
2322 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
2323 EXPECT_CALL(*context,
2324 texParameteri(GL_TEXTURE_2D,
2325 GL_TEXTURE_POOL_CHROMIUM,
2326 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM));
2328 resource_provider->AllocateForTesting(id);
2329 Mock::VerifyAndClearExpectations(context);
2331 // Creating a sampler with the default filter should not change any texture
2332 // parameters.
2334 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
2335 ResourceProvider::ScopedSamplerGL sampler(
2336 resource_provider.get(), id, GL_TEXTURE_2D, GL_LINEAR);
2337 Mock::VerifyAndClearExpectations(context);
2340 // Using a different filter should be reflected in the texture parameters.
2342 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
2343 EXPECT_CALL(
2344 *context,
2345 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
2346 EXPECT_CALL(
2347 *context,
2348 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
2349 ResourceProvider::ScopedSamplerGL sampler(
2350 resource_provider.get(), id, GL_TEXTURE_2D, GL_NEAREST);
2351 Mock::VerifyAndClearExpectations(context);
2354 // Test resetting to the default filter.
2356 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
2357 EXPECT_CALL(*context,
2358 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
2359 EXPECT_CALL(*context,
2360 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
2361 ResourceProvider::ScopedSamplerGL sampler(
2362 resource_provider.get(), id, GL_TEXTURE_2D, GL_LINEAR);
2363 Mock::VerifyAndClearExpectations(context);
2367 TEST_P(ResourceProviderTest, ManagedResource) {
2368 // Sampling is only supported for GL textures.
2369 if (GetParam() != ResourceProvider::GLTexture)
2370 return;
2372 scoped_ptr<TextureStateTrackingContext> context_owned(
2373 new TextureStateTrackingContext);
2374 TextureStateTrackingContext* context = context_owned.get();
2376 FakeOutputSurfaceClient output_surface_client;
2377 scoped_ptr<OutputSurface> output_surface(
2378 FakeOutputSurface::Create3d(context_owned.Pass()));
2379 CHECK(output_surface->BindToClient(&output_surface_client));
2381 scoped_ptr<ResourceProvider> resource_provider(
2382 ResourceProvider::Create(output_surface.get(),
2383 shared_bitmap_manager_.get(),
2384 gpu_memory_buffer_manager_.get(),
2385 NULL,
2387 false,
2388 1));
2390 gfx::Size size(1, 1);
2391 ResourceFormat format = RGBA_8888;
2392 int texture_id = 1;
2394 // Check that the texture gets created with the right sampler settings.
2395 ResourceProvider::ResourceId id = resource_provider->CreateManagedResource(
2396 size,
2397 GL_TEXTURE_2D,
2398 GL_CLAMP_TO_EDGE,
2399 ResourceProvider::TextureHintImmutable,
2400 format);
2401 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
2402 EXPECT_CALL(*context,
2403 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
2404 EXPECT_CALL(*context,
2405 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
2406 EXPECT_CALL(
2407 *context,
2408 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
2409 EXPECT_CALL(
2410 *context,
2411 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
2412 EXPECT_CALL(*context,
2413 texParameteri(GL_TEXTURE_2D,
2414 GL_TEXTURE_POOL_CHROMIUM,
2415 GL_TEXTURE_POOL_MANAGED_CHROMIUM));
2416 resource_provider->CreateForTesting(id);
2417 EXPECT_NE(0u, id);
2419 Mock::VerifyAndClearExpectations(context);
2422 TEST_P(ResourceProviderTest, TextureWrapMode) {
2423 // Sampling is only supported for GL textures.
2424 if (GetParam() != ResourceProvider::GLTexture)
2425 return;
2427 scoped_ptr<TextureStateTrackingContext> context_owned(
2428 new TextureStateTrackingContext);
2429 TextureStateTrackingContext* context = context_owned.get();
2431 FakeOutputSurfaceClient output_surface_client;
2432 scoped_ptr<OutputSurface> output_surface(
2433 FakeOutputSurface::Create3d(context_owned.Pass()));
2434 CHECK(output_surface->BindToClient(&output_surface_client));
2436 scoped_ptr<ResourceProvider> resource_provider(
2437 ResourceProvider::Create(output_surface.get(),
2438 shared_bitmap_manager_.get(),
2439 gpu_memory_buffer_manager_.get(),
2440 NULL,
2442 false,
2443 1));
2445 gfx::Size size(1, 1);
2446 ResourceFormat format = RGBA_8888;
2447 GLenum texture_pool = GL_TEXTURE_POOL_UNMANAGED_CHROMIUM;
2449 for (int texture_id = 1; texture_id <= 2; ++texture_id) {
2450 GLint wrap_mode = texture_id == 1 ? GL_CLAMP_TO_EDGE : GL_REPEAT;
2451 // Check that the texture gets created with the right sampler settings.
2452 ResourceProvider::ResourceId id = resource_provider->CreateGLTexture(
2453 size,
2454 GL_TEXTURE_2D,
2455 texture_pool,
2456 wrap_mode,
2457 ResourceProvider::TextureHintImmutable,
2458 format);
2459 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
2460 EXPECT_CALL(*context,
2461 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
2462 EXPECT_CALL(*context,
2463 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
2464 EXPECT_CALL(*context,
2465 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap_mode));
2466 EXPECT_CALL(*context,
2467 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap_mode));
2468 EXPECT_CALL(*context,
2469 texParameteri(GL_TEXTURE_2D,
2470 GL_TEXTURE_POOL_CHROMIUM,
2471 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM));
2472 resource_provider->CreateForTesting(id);
2473 EXPECT_NE(0u, id);
2475 Mock::VerifyAndClearExpectations(context);
2479 TEST_P(ResourceProviderTest, TextureHint) {
2480 // Sampling is only supported for GL textures.
2481 if (GetParam() != ResourceProvider::GLTexture)
2482 return;
2484 scoped_ptr<TextureStateTrackingContext> context_owned(
2485 new TextureStateTrackingContext);
2486 TextureStateTrackingContext* context = context_owned.get();
2487 context->set_support_texture_storage(true);
2488 context->set_support_texture_usage(true);
2490 FakeOutputSurfaceClient output_surface_client;
2491 scoped_ptr<OutputSurface> output_surface(
2492 FakeOutputSurface::Create3d(context_owned.Pass()));
2493 CHECK(output_surface->BindToClient(&output_surface_client));
2495 scoped_ptr<ResourceProvider> resource_provider(
2496 ResourceProvider::Create(output_surface.get(),
2497 shared_bitmap_manager_.get(),
2498 gpu_memory_buffer_manager_.get(),
2499 NULL,
2501 false,
2502 1));
2504 gfx::Size size(1, 1);
2505 ResourceFormat format = RGBA_8888;
2506 GLenum texture_pool = GL_TEXTURE_POOL_UNMANAGED_CHROMIUM;
2508 const ResourceProvider::TextureHint hints[4] = {
2509 ResourceProvider::TextureHintDefault,
2510 ResourceProvider::TextureHintImmutable,
2511 ResourceProvider::TextureHintFramebuffer,
2512 ResourceProvider::TextureHintImmutableFramebuffer,
2514 for (GLuint texture_id = 1; texture_id <= arraysize(hints); ++texture_id) {
2515 // Check that the texture gets created with the right sampler settings.
2516 ResourceProvider::ResourceId id =
2517 resource_provider->CreateGLTexture(size,
2518 GL_TEXTURE_2D,
2519 texture_pool,
2520 GL_CLAMP_TO_EDGE,
2521 hints[texture_id - 1],
2522 format);
2523 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
2524 EXPECT_CALL(*context,
2525 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
2526 EXPECT_CALL(*context,
2527 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
2528 EXPECT_CALL(
2529 *context,
2530 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
2531 EXPECT_CALL(
2532 *context,
2533 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
2534 EXPECT_CALL(*context,
2535 texParameteri(GL_TEXTURE_2D,
2536 GL_TEXTURE_POOL_CHROMIUM,
2537 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM));
2538 // Check only TextureHintFramebuffer set GL_TEXTURE_USAGE_ANGLE.
2539 bool is_framebuffer_hint =
2540 hints[texture_id - 1] & ResourceProvider::TextureHintFramebuffer;
2541 EXPECT_CALL(*context,
2542 texParameteri(GL_TEXTURE_2D,
2543 GL_TEXTURE_USAGE_ANGLE,
2544 GL_FRAMEBUFFER_ATTACHMENT_ANGLE))
2545 .Times(is_framebuffer_hint ? 1 : 0);
2546 resource_provider->CreateForTesting(id);
2547 EXPECT_NE(0u, id);
2549 Mock::VerifyAndClearExpectations(context);
2553 TEST_P(ResourceProviderTest, TextureMailbox_SharedMemory) {
2554 if (GetParam() != ResourceProvider::Bitmap)
2555 return;
2557 gfx::Size size(64, 64);
2558 const uint32_t kBadBeef = 0xbadbeef;
2559 scoped_ptr<base::SharedMemory> shared_memory(
2560 CreateAndFillSharedMemory(size, kBadBeef));
2562 FakeOutputSurfaceClient output_surface_client;
2563 scoped_ptr<OutputSurface> output_surface(
2564 FakeOutputSurface::CreateSoftware(make_scoped_ptr(
2565 new SoftwareOutputDevice)));
2566 CHECK(output_surface->BindToClient(&output_surface_client));
2568 scoped_ptr<ResourceProvider> resource_provider(
2569 ResourceProvider::Create(output_surface.get(),
2570 shared_bitmap_manager_.get(),
2571 gpu_memory_buffer_manager_.get(),
2572 main_thread_task_runner_.get(),
2574 false,
2575 1));
2577 uint32 release_sync_point = 0;
2578 bool lost_resource = false;
2579 BlockingTaskRunner* main_thread_task_runner = NULL;
2580 scoped_ptr<SingleReleaseCallbackImpl> callback =
2581 SingleReleaseCallbackImpl::Create(base::Bind(&ReleaseCallback,
2582 &release_sync_point,
2583 &lost_resource,
2584 &main_thread_task_runner));
2585 TextureMailbox mailbox(shared_memory.get(), size);
2587 ResourceProvider::ResourceId id =
2588 resource_provider->CreateResourceFromTextureMailbox(
2589 mailbox, callback.Pass());
2590 EXPECT_NE(0u, id);
2593 ResourceProvider::ScopedReadLockSoftware lock(resource_provider.get(), id);
2594 const SkBitmap* sk_bitmap = lock.sk_bitmap();
2595 EXPECT_EQ(sk_bitmap->width(), size.width());
2596 EXPECT_EQ(sk_bitmap->height(), size.height());
2597 EXPECT_EQ(*sk_bitmap->getAddr32(16, 16), kBadBeef);
2600 resource_provider->DeleteResource(id);
2601 EXPECT_EQ(0u, release_sync_point);
2602 EXPECT_FALSE(lost_resource);
2603 EXPECT_EQ(main_thread_task_runner_.get(), main_thread_task_runner);
2606 TEST_P(ResourceProviderTest, TextureMailbox_GLTexture2D) {
2607 // Mailboxing is only supported for GL textures.
2608 if (GetParam() != ResourceProvider::GLTexture)
2609 return;
2611 scoped_ptr<TextureStateTrackingContext> context_owned(
2612 new TextureStateTrackingContext);
2613 TextureStateTrackingContext* context = context_owned.get();
2615 FakeOutputSurfaceClient output_surface_client;
2616 scoped_ptr<OutputSurface> output_surface(
2617 FakeOutputSurface::Create3d(context_owned.Pass()));
2618 CHECK(output_surface->BindToClient(&output_surface_client));
2620 scoped_ptr<ResourceProvider> resource_provider(
2621 ResourceProvider::Create(output_surface.get(),
2622 shared_bitmap_manager_.get(),
2623 gpu_memory_buffer_manager_.get(),
2624 main_thread_task_runner_.get(),
2626 false,
2627 1));
2629 unsigned texture_id = 1;
2630 uint32 sync_point = 30;
2631 unsigned target = GL_TEXTURE_2D;
2633 EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
2634 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
2635 EXPECT_CALL(*context, insertSyncPoint()).Times(0);
2636 EXPECT_CALL(*context, produceTextureCHROMIUM(_, _)).Times(0);
2637 EXPECT_CALL(*context, consumeTextureCHROMIUM(_, _)).Times(0);
2639 gpu::Mailbox gpu_mailbox;
2640 memcpy(gpu_mailbox.name, "Hello world", strlen("Hello world") + 1);
2641 uint32 release_sync_point = 0;
2642 bool lost_resource = false;
2643 BlockingTaskRunner* main_thread_task_runner = NULL;
2644 scoped_ptr<SingleReleaseCallbackImpl> callback =
2645 SingleReleaseCallbackImpl::Create(base::Bind(&ReleaseCallback,
2646 &release_sync_point,
2647 &lost_resource,
2648 &main_thread_task_runner));
2650 TextureMailbox mailbox(gpu_mailbox, target, sync_point);
2652 ResourceProvider::ResourceId id =
2653 resource_provider->CreateResourceFromTextureMailbox(
2654 mailbox, callback.Pass());
2655 EXPECT_NE(0u, id);
2657 Mock::VerifyAndClearExpectations(context);
2660 // Mailbox sync point WaitSyncPoint before using the texture.
2661 EXPECT_CALL(*context, waitSyncPoint(sync_point));
2662 resource_provider->WaitSyncPointIfNeeded(id);
2663 Mock::VerifyAndClearExpectations(context);
2665 // Using the texture does a consume of the mailbox.
2666 EXPECT_CALL(*context, bindTexture(target, texture_id));
2667 EXPECT_CALL(*context, consumeTextureCHROMIUM(target, _));
2669 EXPECT_CALL(*context, insertSyncPoint()).Times(0);
2670 EXPECT_CALL(*context, produceTextureCHROMIUM(_, _)).Times(0);
2672 ResourceProvider::ScopedReadLockGL lock(resource_provider.get(), id);
2673 Mock::VerifyAndClearExpectations(context);
2675 // When done with it, a sync point should be inserted, but no produce is
2676 // necessary.
2677 EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
2678 EXPECT_CALL(*context, insertSyncPoint());
2679 EXPECT_CALL(*context, produceTextureCHROMIUM(_, _)).Times(0);
2681 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
2682 EXPECT_CALL(*context, consumeTextureCHROMIUM(_, _)).Times(0);
2685 resource_provider->DeleteResource(id);
2686 EXPECT_EQ(0u, release_sync_point);
2687 EXPECT_FALSE(lost_resource);
2688 EXPECT_EQ(main_thread_task_runner_.get(), main_thread_task_runner);
2691 TEST_P(ResourceProviderTest, TextureMailbox_GLTextureExternalOES) {
2692 // Mailboxing is only supported for GL textures.
2693 if (GetParam() != ResourceProvider::GLTexture)
2694 return;
2696 scoped_ptr<TextureStateTrackingContext> context_owned(
2697 new TextureStateTrackingContext);
2698 TextureStateTrackingContext* context = context_owned.get();
2700 FakeOutputSurfaceClient output_surface_client;
2701 scoped_ptr<OutputSurface> output_surface(
2702 FakeOutputSurface::Create3d(context_owned.Pass()));
2703 CHECK(output_surface->BindToClient(&output_surface_client));
2705 scoped_ptr<ResourceProvider> resource_provider(
2706 ResourceProvider::Create(output_surface.get(),
2707 shared_bitmap_manager_.get(),
2708 gpu_memory_buffer_manager_.get(),
2709 NULL,
2711 false,
2712 1));
2714 unsigned texture_id = 1;
2715 uint32 sync_point = 30;
2716 unsigned target = GL_TEXTURE_EXTERNAL_OES;
2718 EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
2719 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
2720 EXPECT_CALL(*context, insertSyncPoint()).Times(0);
2721 EXPECT_CALL(*context, produceTextureCHROMIUM(_, _)).Times(0);
2722 EXPECT_CALL(*context, consumeTextureCHROMIUM(_, _)).Times(0);
2724 gpu::Mailbox gpu_mailbox;
2725 memcpy(gpu_mailbox.name, "Hello world", strlen("Hello world") + 1);
2726 scoped_ptr<SingleReleaseCallbackImpl> callback =
2727 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback));
2729 TextureMailbox mailbox(gpu_mailbox, target, sync_point);
2731 ResourceProvider::ResourceId id =
2732 resource_provider->CreateResourceFromTextureMailbox(
2733 mailbox, callback.Pass());
2734 EXPECT_NE(0u, id);
2736 Mock::VerifyAndClearExpectations(context);
2739 // Mailbox sync point WaitSyncPoint before using the texture.
2740 EXPECT_CALL(*context, waitSyncPoint(sync_point));
2741 resource_provider->WaitSyncPointIfNeeded(id);
2742 Mock::VerifyAndClearExpectations(context);
2744 // Using the texture does a consume of the mailbox.
2745 EXPECT_CALL(*context, bindTexture(target, texture_id));
2746 EXPECT_CALL(*context, consumeTextureCHROMIUM(target, _));
2748 EXPECT_CALL(*context, insertSyncPoint()).Times(0);
2749 EXPECT_CALL(*context, produceTextureCHROMIUM(_, _)).Times(0);
2751 ResourceProvider::ScopedReadLockGL lock(resource_provider.get(), id);
2752 Mock::VerifyAndClearExpectations(context);
2754 // When done with it, a sync point should be inserted, but no produce is
2755 // necessary.
2756 EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
2757 EXPECT_CALL(*context, insertSyncPoint());
2758 EXPECT_CALL(*context, produceTextureCHROMIUM(_, _)).Times(0);
2760 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
2761 EXPECT_CALL(*context, consumeTextureCHROMIUM(_, _)).Times(0);
2765 TEST_P(ResourceProviderTest,
2766 TextureMailbox_WaitSyncPointIfNeeded_WithSyncPoint) {
2767 // Mailboxing is only supported for GL textures.
2768 if (GetParam() != ResourceProvider::GLTexture)
2769 return;
2771 scoped_ptr<TextureStateTrackingContext> context_owned(
2772 new TextureStateTrackingContext);
2773 TextureStateTrackingContext* context = context_owned.get();
2775 FakeOutputSurfaceClient output_surface_client;
2776 scoped_ptr<OutputSurface> output_surface(
2777 FakeOutputSurface::Create3d(context_owned.Pass()));
2778 CHECK(output_surface->BindToClient(&output_surface_client));
2780 scoped_ptr<ResourceProvider> resource_provider(
2781 ResourceProvider::Create(output_surface.get(),
2782 shared_bitmap_manager_.get(),
2783 gpu_memory_buffer_manager_.get(),
2784 NULL,
2786 false,
2787 1));
2789 uint32 sync_point = 30;
2790 unsigned target = GL_TEXTURE_2D;
2792 EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
2793 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
2794 EXPECT_CALL(*context, insertSyncPoint()).Times(0);
2795 EXPECT_CALL(*context, produceTextureCHROMIUM(_, _)).Times(0);
2796 EXPECT_CALL(*context, consumeTextureCHROMIUM(_, _)).Times(0);
2798 gpu::Mailbox gpu_mailbox;
2799 memcpy(gpu_mailbox.name, "Hello world", strlen("Hello world") + 1);
2800 scoped_ptr<SingleReleaseCallbackImpl> callback =
2801 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback));
2803 TextureMailbox mailbox(gpu_mailbox, target, sync_point);
2805 ResourceProvider::ResourceId id =
2806 resource_provider->CreateResourceFromTextureMailbox(mailbox,
2807 callback.Pass());
2808 EXPECT_NE(0u, id);
2810 Mock::VerifyAndClearExpectations(context);
2813 // First call to WaitSyncPointIfNeeded should call waitSyncPoint.
2814 EXPECT_CALL(*context, waitSyncPoint(sync_point));
2815 resource_provider->WaitSyncPointIfNeeded(id);
2816 Mock::VerifyAndClearExpectations(context);
2818 // Subsequent calls to WaitSyncPointIfNeeded shouldn't call waitSyncPoint.
2819 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
2820 resource_provider->WaitSyncPointIfNeeded(id);
2821 Mock::VerifyAndClearExpectations(context);
2825 TEST_P(ResourceProviderTest, TextureMailbox_WaitSyncPointIfNeeded_NoSyncPoint) {
2826 // Mailboxing is only supported for GL textures.
2827 if (GetParam() != ResourceProvider::GLTexture)
2828 return;
2830 scoped_ptr<TextureStateTrackingContext> context_owned(
2831 new TextureStateTrackingContext);
2832 TextureStateTrackingContext* context = context_owned.get();
2834 FakeOutputSurfaceClient output_surface_client;
2835 scoped_ptr<OutputSurface> output_surface(
2836 FakeOutputSurface::Create3d(context_owned.Pass()));
2837 CHECK(output_surface->BindToClient(&output_surface_client));
2839 scoped_ptr<ResourceProvider> resource_provider(
2840 ResourceProvider::Create(output_surface.get(),
2841 shared_bitmap_manager_.get(),
2842 gpu_memory_buffer_manager_.get(),
2843 NULL,
2845 false,
2846 1));
2848 uint32 sync_point = 0;
2849 unsigned target = GL_TEXTURE_2D;
2851 EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
2852 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
2853 EXPECT_CALL(*context, insertSyncPoint()).Times(0);
2854 EXPECT_CALL(*context, produceTextureCHROMIUM(_, _)).Times(0);
2855 EXPECT_CALL(*context, consumeTextureCHROMIUM(_, _)).Times(0);
2857 gpu::Mailbox gpu_mailbox;
2858 memcpy(gpu_mailbox.name, "Hello world", strlen("Hello world") + 1);
2859 scoped_ptr<SingleReleaseCallbackImpl> callback =
2860 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback));
2862 TextureMailbox mailbox(gpu_mailbox, target, sync_point);
2864 ResourceProvider::ResourceId id =
2865 resource_provider->CreateResourceFromTextureMailbox(mailbox,
2866 callback.Pass());
2867 EXPECT_NE(0u, id);
2869 Mock::VerifyAndClearExpectations(context);
2872 // WaitSyncPointIfNeeded with sync_point == 0 shouldn't call waitSyncPoint.
2873 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
2874 resource_provider->WaitSyncPointIfNeeded(id);
2875 Mock::VerifyAndClearExpectations(context);
2879 class AllocationTrackingContext3D : public TestWebGraphicsContext3D {
2880 public:
2881 MOCK_METHOD0(NextTextureId, GLuint());
2882 MOCK_METHOD1(RetireTextureId, void(GLuint id));
2883 MOCK_METHOD2(bindTexture, void(GLenum target, GLuint texture));
2884 MOCK_METHOD5(texStorage2DEXT,
2885 void(GLenum target,
2886 GLint levels,
2887 GLuint internalformat,
2888 GLint width,
2889 GLint height));
2890 MOCK_METHOD9(texImage2D,
2891 void(GLenum target,
2892 GLint level,
2893 GLenum internalformat,
2894 GLsizei width,
2895 GLsizei height,
2896 GLint border,
2897 GLenum format,
2898 GLenum type,
2899 const void* pixels));
2900 MOCK_METHOD9(texSubImage2D,
2901 void(GLenum target,
2902 GLint level,
2903 GLint xoffset,
2904 GLint yoffset,
2905 GLsizei width,
2906 GLsizei height,
2907 GLenum format,
2908 GLenum type,
2909 const void* pixels));
2910 MOCK_METHOD9(asyncTexImage2DCHROMIUM,
2911 void(GLenum target,
2912 GLint level,
2913 GLenum internalformat,
2914 GLsizei width,
2915 GLsizei height,
2916 GLint border,
2917 GLenum format,
2918 GLenum type,
2919 const void* pixels));
2920 MOCK_METHOD9(asyncTexSubImage2DCHROMIUM,
2921 void(GLenum target,
2922 GLint level,
2923 GLint xoffset,
2924 GLint yoffset,
2925 GLsizei width,
2926 GLsizei height,
2927 GLenum format,
2928 GLenum type,
2929 const void* pixels));
2930 MOCK_METHOD8(compressedTexImage2D,
2931 void(GLenum target,
2932 GLint level,
2933 GLenum internalformat,
2934 GLsizei width,
2935 GLsizei height,
2936 GLint border,
2937 GLsizei image_size,
2938 const void* data));
2939 MOCK_METHOD1(waitAsyncTexImage2DCHROMIUM, void(GLenum));
2940 MOCK_METHOD4(createImageCHROMIUM,
2941 GLuint(ClientBuffer, GLsizei, GLsizei, GLenum));
2942 MOCK_METHOD1(destroyImageCHROMIUM, void(GLuint));
2943 MOCK_METHOD2(bindTexImage2DCHROMIUM, void(GLenum, GLint));
2944 MOCK_METHOD2(releaseTexImage2DCHROMIUM, void(GLenum, GLint));
2946 // We're mocking bindTexture, so we override
2947 // TestWebGraphicsContext3D::texParameteri to avoid assertions related to the
2948 // currently bound texture.
2949 virtual void texParameteri(GLenum target, GLenum pname, GLint param) {}
2952 TEST_P(ResourceProviderTest, TextureAllocation) {
2953 // Only for GL textures.
2954 if (GetParam() != ResourceProvider::GLTexture)
2955 return;
2956 scoped_ptr<AllocationTrackingContext3D> context_owned(
2957 new StrictMock<AllocationTrackingContext3D>);
2958 AllocationTrackingContext3D* context = context_owned.get();
2960 FakeOutputSurfaceClient output_surface_client;
2961 scoped_ptr<OutputSurface> output_surface(
2962 FakeOutputSurface::Create3d(context_owned.Pass()));
2963 CHECK(output_surface->BindToClient(&output_surface_client));
2965 scoped_ptr<ResourceProvider> resource_provider(
2966 ResourceProvider::Create(output_surface.get(),
2967 shared_bitmap_manager_.get(),
2968 gpu_memory_buffer_manager_.get(),
2969 NULL,
2971 false,
2972 1));
2974 gfx::Size size(2, 2);
2975 gfx::Vector2d offset(0, 0);
2976 gfx::Rect rect(0, 0, 2, 2);
2977 ResourceFormat format = RGBA_8888;
2978 ResourceProvider::ResourceId id = 0;
2979 uint8_t pixels[16] = { 0 };
2980 int texture_id = 123;
2982 // Lazy allocation. Don't allocate when creating the resource.
2983 id = resource_provider->CreateResource(
2984 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
2986 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
2987 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(1);
2988 resource_provider->CreateForTesting(id);
2990 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
2991 resource_provider->DeleteResource(id);
2993 Mock::VerifyAndClearExpectations(context);
2995 // Do allocate when we set the pixels.
2996 id = resource_provider->CreateResource(
2997 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
2999 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3000 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(3);
3001 EXPECT_CALL(*context, texImage2D(_, _, _, 2, 2, _, _, _, _)).Times(1);
3002 EXPECT_CALL(*context, texSubImage2D(_, _, _, _, 2, 2, _, _, _)).Times(1);
3003 resource_provider->SetPixels(id, pixels, rect, rect, offset);
3005 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3006 resource_provider->DeleteResource(id);
3008 Mock::VerifyAndClearExpectations(context);
3010 // Same for async version.
3011 id = resource_provider->CreateResource(
3012 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
3013 resource_provider->AcquirePixelBuffer(id);
3015 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3016 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
3017 EXPECT_CALL(*context, asyncTexImage2DCHROMIUM(_, _, _, 2, 2, _, _, _, _))
3018 .Times(1);
3019 resource_provider->BeginSetPixels(id);
3020 ASSERT_TRUE(resource_provider->DidSetPixelsComplete(id));
3022 resource_provider->ReleasePixelBuffer(id);
3024 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3025 resource_provider->DeleteResource(id);
3027 Mock::VerifyAndClearExpectations(context);
3030 TEST_P(ResourceProviderTest, TextureAllocationHint) {
3031 // Only for GL textures.
3032 if (GetParam() != ResourceProvider::GLTexture)
3033 return;
3034 scoped_ptr<AllocationTrackingContext3D> context_owned(
3035 new StrictMock<AllocationTrackingContext3D>);
3036 AllocationTrackingContext3D* context = context_owned.get();
3037 context->set_support_texture_storage(true);
3038 context->set_support_texture_usage(true);
3040 FakeOutputSurfaceClient output_surface_client;
3041 scoped_ptr<OutputSurface> output_surface(
3042 FakeOutputSurface::Create3d(context_owned.Pass()));
3043 CHECK(output_surface->BindToClient(&output_surface_client));
3045 scoped_ptr<ResourceProvider> resource_provider(
3046 ResourceProvider::Create(output_surface.get(),
3047 shared_bitmap_manager_.get(),
3048 gpu_memory_buffer_manager_.get(),
3049 NULL,
3051 false,
3052 1));
3054 gfx::Size size(2, 2);
3056 const ResourceFormat formats[2] = {RGBA_8888, BGRA_8888};
3057 const ResourceProvider::TextureHint hints[4] = {
3058 ResourceProvider::TextureHintDefault,
3059 ResourceProvider::TextureHintImmutable,
3060 ResourceProvider::TextureHintFramebuffer,
3061 ResourceProvider::TextureHintImmutableFramebuffer,
3063 for (size_t i = 0; i < arraysize(formats); ++i) {
3064 for (GLuint texture_id = 1; texture_id <= arraysize(hints); ++texture_id) {
3065 // Lazy allocation. Don't allocate when creating the resource.
3066 ResourceProvider::ResourceId id = resource_provider->CreateResource(
3067 size, GL_CLAMP_TO_EDGE, hints[texture_id - 1], formats[i]);
3069 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3070 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
3071 bool is_immutable_hint =
3072 hints[texture_id - 1] & ResourceProvider::TextureHintImmutable;
3073 bool support_immutable_texture =
3074 is_immutable_hint && formats[i] == RGBA_8888;
3075 EXPECT_CALL(*context, texStorage2DEXT(_, _, _, 2, 2))
3076 .Times(support_immutable_texture ? 1 : 0);
3077 EXPECT_CALL(*context, texImage2D(_, _, _, 2, 2, _, _, _, _))
3078 .Times(support_immutable_texture ? 0 : 1);
3079 resource_provider->AllocateForTesting(id);
3081 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3082 resource_provider->DeleteResource(id);
3084 Mock::VerifyAndClearExpectations(context);
3089 TEST_P(ResourceProviderTest, TextureAllocationHint_BGRA) {
3090 // Only for GL textures.
3091 if (GetParam() != ResourceProvider::GLTexture)
3092 return;
3093 scoped_ptr<AllocationTrackingContext3D> context_owned(
3094 new StrictMock<AllocationTrackingContext3D>);
3095 AllocationTrackingContext3D* context = context_owned.get();
3096 context->set_support_texture_format_bgra8888(true);
3097 context->set_support_texture_storage(true);
3098 context->set_support_texture_usage(true);
3100 FakeOutputSurfaceClient output_surface_client;
3101 scoped_ptr<OutputSurface> output_surface(
3102 FakeOutputSurface::Create3d(context_owned.Pass()));
3103 CHECK(output_surface->BindToClient(&output_surface_client));
3105 scoped_ptr<ResourceProvider> resource_provider(
3106 ResourceProvider::Create(output_surface.get(),
3107 shared_bitmap_manager_.get(),
3108 gpu_memory_buffer_manager_.get(),
3109 NULL,
3111 false,
3112 1));
3114 gfx::Size size(2, 2);
3115 const ResourceFormat formats[2] = {RGBA_8888, BGRA_8888};
3117 const ResourceProvider::TextureHint hints[4] = {
3118 ResourceProvider::TextureHintDefault,
3119 ResourceProvider::TextureHintImmutable,
3120 ResourceProvider::TextureHintFramebuffer,
3121 ResourceProvider::TextureHintImmutableFramebuffer,
3123 for (size_t i = 0; i < arraysize(formats); ++i) {
3124 for (GLuint texture_id = 1; texture_id <= arraysize(hints); ++texture_id) {
3125 // Lazy allocation. Don't allocate when creating the resource.
3126 ResourceProvider::ResourceId id = resource_provider->CreateResource(
3127 size, GL_CLAMP_TO_EDGE, hints[texture_id - 1], formats[i]);
3129 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3130 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
3131 bool is_immutable_hint =
3132 hints[texture_id - 1] & ResourceProvider::TextureHintImmutable;
3133 EXPECT_CALL(*context, texStorage2DEXT(_, _, _, 2, 2))
3134 .Times(is_immutable_hint ? 1 : 0);
3135 EXPECT_CALL(*context, texImage2D(_, _, _, 2, 2, _, _, _, _))
3136 .Times(is_immutable_hint ? 0 : 1);
3137 resource_provider->AllocateForTesting(id);
3139 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3140 resource_provider->DeleteResource(id);
3142 Mock::VerifyAndClearExpectations(context);
3147 TEST_P(ResourceProviderTest, PixelBuffer_GLTexture) {
3148 if (GetParam() != ResourceProvider::GLTexture)
3149 return;
3150 scoped_ptr<AllocationTrackingContext3D> context_owned(
3151 new StrictMock<AllocationTrackingContext3D>);
3152 AllocationTrackingContext3D* context = context_owned.get();
3154 FakeOutputSurfaceClient output_surface_client;
3155 scoped_ptr<OutputSurface> output_surface(
3156 FakeOutputSurface::Create3d(context_owned.Pass()));
3157 CHECK(output_surface->BindToClient(&output_surface_client));
3159 gfx::Size size(2, 2);
3160 ResourceFormat format = RGBA_8888;
3161 ResourceProvider::ResourceId id = 0;
3162 int texture_id = 123;
3164 scoped_ptr<ResourceProvider> resource_provider(
3165 ResourceProvider::Create(output_surface.get(),
3166 shared_bitmap_manager_.get(),
3167 gpu_memory_buffer_manager_.get(),
3168 NULL,
3170 false,
3171 1));
3173 id = resource_provider->CreateResource(
3174 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
3175 resource_provider->AcquirePixelBuffer(id);
3177 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3178 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
3179 EXPECT_CALL(*context, asyncTexImage2DCHROMIUM(_, _, _, 2, 2, _, _, _, _))
3180 .Times(1);
3181 resource_provider->BeginSetPixels(id);
3183 EXPECT_TRUE(resource_provider->DidSetPixelsComplete(id));
3185 resource_provider->ReleasePixelBuffer(id);
3187 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3188 resource_provider->DeleteResource(id);
3190 Mock::VerifyAndClearExpectations(context);
3193 TEST_P(ResourceProviderTest, ForcingAsyncUploadToComplete) {
3194 // Only for GL textures.
3195 if (GetParam() != ResourceProvider::GLTexture)
3196 return;
3197 scoped_ptr<AllocationTrackingContext3D> context_owned(
3198 new StrictMock<AllocationTrackingContext3D>);
3199 AllocationTrackingContext3D* context = context_owned.get();
3201 FakeOutputSurfaceClient output_surface_client;
3202 scoped_ptr<OutputSurface> output_surface(
3203 FakeOutputSurface::Create3d(context_owned.Pass()));
3204 CHECK(output_surface->BindToClient(&output_surface_client));
3206 gfx::Size size(2, 2);
3207 ResourceFormat format = RGBA_8888;
3208 ResourceProvider::ResourceId id = 0;
3209 int texture_id = 123;
3211 scoped_ptr<ResourceProvider> resource_provider(
3212 ResourceProvider::Create(output_surface.get(),
3213 shared_bitmap_manager_.get(),
3214 gpu_memory_buffer_manager_.get(),
3215 NULL,
3217 false,
3218 1));
3220 id = resource_provider->CreateResource(
3221 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
3222 resource_provider->AcquirePixelBuffer(id);
3224 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3225 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
3226 EXPECT_CALL(*context, asyncTexImage2DCHROMIUM(_, _, _, 2, 2, _, _, _, _))
3227 .Times(1);
3228 resource_provider->BeginSetPixels(id);
3230 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(1);
3231 EXPECT_CALL(*context, waitAsyncTexImage2DCHROMIUM(GL_TEXTURE_2D)).Times(1);
3232 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, 0)).Times(1);
3233 resource_provider->ForceSetPixelsToComplete(id);
3235 resource_provider->ReleasePixelBuffer(id);
3237 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3238 resource_provider->DeleteResource(id);
3240 Mock::VerifyAndClearExpectations(context);
3243 TEST_P(ResourceProviderTest, PixelBufferLostContext) {
3244 scoped_ptr<AllocationTrackingContext3D> context_owned(
3245 new NiceMock<AllocationTrackingContext3D>);
3246 AllocationTrackingContext3D* context = context_owned.get();
3248 FakeOutputSurfaceClient output_surface_client;
3249 scoped_ptr<OutputSurface> output_surface(
3250 FakeOutputSurface::Create3d(context_owned.Pass()));
3251 CHECK(output_surface->BindToClient(&output_surface_client));
3253 gfx::Size size(2, 2);
3254 ResourceFormat format = RGBA_8888;
3255 ResourceProvider::ResourceId id = 0;
3256 int texture_id = 123;
3258 scoped_ptr<ResourceProvider> resource_provider(
3259 ResourceProvider::Create(output_surface.get(),
3260 shared_bitmap_manager_.get(),
3261 gpu_memory_buffer_manager_.get(),
3262 NULL,
3264 false,
3265 1));
3267 EXPECT_CALL(*context, NextTextureId()).WillRepeatedly(Return(texture_id));
3269 id = resource_provider->CreateResource(
3270 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
3271 context->loseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB,
3272 GL_INNOCENT_CONTEXT_RESET_ARB);
3274 resource_provider->AcquirePixelBuffer(id);
3275 int stride;
3276 void* buffer = resource_provider->MapPixelBuffer(id, &stride);
3277 EXPECT_FALSE(buffer);
3278 resource_provider->UnmapPixelBuffer(id);
3279 Mock::VerifyAndClearExpectations(context);
3282 TEST_P(ResourceProviderTest, Image_GLTexture) {
3283 // Only for GL textures.
3284 if (GetParam() != ResourceProvider::GLTexture)
3285 return;
3286 scoped_ptr<AllocationTrackingContext3D> context_owned(
3287 new StrictMock<AllocationTrackingContext3D>);
3288 AllocationTrackingContext3D* context = context_owned.get();
3290 FakeOutputSurfaceClient output_surface_client;
3291 scoped_ptr<OutputSurface> output_surface(
3292 FakeOutputSurface::Create3d(context_owned.Pass()));
3293 CHECK(output_surface->BindToClient(&output_surface_client));
3295 const int kWidth = 2;
3296 const int kHeight = 2;
3297 gfx::Size size(kWidth, kHeight);
3298 ResourceFormat format = RGBA_8888;
3299 ResourceProvider::ResourceId id = 0;
3300 const unsigned kTextureId = 123u;
3301 const unsigned kImageId = 234u;
3303 scoped_ptr<ResourceProvider> resource_provider(
3304 ResourceProvider::Create(output_surface.get(),
3305 shared_bitmap_manager_.get(),
3306 gpu_memory_buffer_manager_.get(),
3307 NULL,
3309 false,
3310 1));
3312 id = resource_provider->CreateResource(
3313 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
3315 EXPECT_CALL(*context, createImageCHROMIUM(_, kWidth, kHeight, GL_RGBA))
3316 .WillOnce(Return(kImageId))
3317 .RetiresOnSaturation();
3319 ResourceProvider::ScopedWriteLockGpuMemoryBuffer lock(
3320 resource_provider.get(), id);
3321 EXPECT_TRUE(!!lock.GetGpuMemoryBuffer());
3324 EXPECT_CALL(*context, NextTextureId())
3325 .WillOnce(Return(kTextureId))
3326 .RetiresOnSaturation();
3327 // Once in CreateTextureId and once in BindForSampling
3328 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kTextureId)).Times(2)
3329 .RetiresOnSaturation();
3330 EXPECT_CALL(*context, bindTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId))
3331 .Times(1)
3332 .RetiresOnSaturation();
3334 ResourceProvider::ScopedSamplerGL lock_gl(
3335 resource_provider.get(), id, GL_TEXTURE_2D, GL_LINEAR);
3336 EXPECT_EQ(kTextureId, lock_gl.texture_id());
3340 ResourceProvider::ScopedWriteLockGpuMemoryBuffer lock(
3341 resource_provider.get(), id);
3342 EXPECT_TRUE(!!lock.GetGpuMemoryBuffer());
3345 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kTextureId)).Times(1)
3346 .RetiresOnSaturation();
3347 EXPECT_CALL(*context, releaseTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId))
3348 .Times(1)
3349 .RetiresOnSaturation();
3350 EXPECT_CALL(*context, bindTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId))
3351 .Times(1)
3352 .RetiresOnSaturation();
3353 EXPECT_CALL(*context, RetireTextureId(kTextureId))
3354 .Times(1)
3355 .RetiresOnSaturation();
3357 ResourceProvider::ScopedSamplerGL lock_gl(
3358 resource_provider.get(), id, GL_TEXTURE_2D, GL_LINEAR);
3359 EXPECT_EQ(kTextureId, lock_gl.texture_id());
3362 EXPECT_CALL(*context, destroyImageCHROMIUM(kImageId))
3363 .Times(1)
3364 .RetiresOnSaturation();
3367 TEST_P(ResourceProviderTest, CopyResource_GLTexture) {
3368 if (GetParam() != ResourceProvider::GLTexture)
3369 return;
3370 scoped_ptr<AllocationTrackingContext3D> context_owned(
3371 new StrictMock<AllocationTrackingContext3D>);
3372 AllocationTrackingContext3D* context = context_owned.get();
3373 context_owned->set_support_sync_query(true);
3375 FakeOutputSurfaceClient output_surface_client;
3376 scoped_ptr<OutputSurface> output_surface(
3377 FakeOutputSurface::Create3d(context_owned.Pass()));
3378 ASSERT_TRUE(output_surface->BindToClient(&output_surface_client));
3380 const int kWidth = 2;
3381 const int kHeight = 2;
3382 gfx::Size size(kWidth, kHeight);
3383 ResourceFormat format = RGBA_8888;
3384 ResourceProvider::ResourceId source_id = 0;
3385 ResourceProvider::ResourceId dest_id = 0;
3386 const unsigned kSourceTextureId = 123u;
3387 const unsigned kDestTextureId = 321u;
3388 const unsigned kImageId = 234u;
3390 scoped_ptr<ResourceProvider> resource_provider(
3391 ResourceProvider::Create(output_surface.get(),
3392 shared_bitmap_manager_.get(),
3393 gpu_memory_buffer_manager_.get(),
3394 NULL,
3396 false,
3397 1));
3399 source_id = resource_provider->CreateResource(
3400 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
3402 EXPECT_CALL(*context, createImageCHROMIUM(_, kWidth, kHeight, GL_RGBA))
3403 .WillOnce(Return(kImageId))
3404 .RetiresOnSaturation();
3406 ResourceProvider::ScopedWriteLockGpuMemoryBuffer lock(
3407 resource_provider.get(), source_id);
3408 EXPECT_TRUE(!!lock.GetGpuMemoryBuffer());
3410 Mock::VerifyAndClearExpectations(context);
3412 dest_id = resource_provider->CreateResource(
3413 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
3415 EXPECT_CALL(*context, NextTextureId())
3416 .WillOnce(Return(kDestTextureId))
3417 .RetiresOnSaturation();
3418 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kDestTextureId))
3419 .Times(1)
3420 .RetiresOnSaturation();
3421 EXPECT_CALL(*context, NextTextureId())
3422 .WillOnce(Return(kSourceTextureId))
3423 .RetiresOnSaturation();
3424 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kSourceTextureId))
3425 .Times(2)
3426 .RetiresOnSaturation();
3427 EXPECT_CALL(*context, bindTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId))
3428 .Times(1)
3429 .RetiresOnSaturation();
3430 resource_provider->CopyResource(source_id, dest_id);
3431 Mock::VerifyAndClearExpectations(context);
3433 EXPECT_CALL(*context, destroyImageCHROMIUM(kImageId))
3434 .Times(1)
3435 .RetiresOnSaturation();
3436 EXPECT_CALL(*context, RetireTextureId(kSourceTextureId))
3437 .Times(1)
3438 .RetiresOnSaturation();
3439 EXPECT_CALL(*context, RetireTextureId(kDestTextureId))
3440 .Times(1)
3441 .RetiresOnSaturation();
3442 resource_provider->DeleteResource(source_id);
3443 resource_provider->DeleteResource(dest_id);
3446 void InitializeGLAndCheck(ContextSharedData* shared_data,
3447 ResourceProvider* resource_provider,
3448 FakeOutputSurface* output_surface) {
3449 scoped_ptr<ResourceProviderContext> context_owned =
3450 ResourceProviderContext::Create(shared_data);
3451 ResourceProviderContext* context = context_owned.get();
3453 scoped_refptr<TestContextProvider> context_provider =
3454 TestContextProvider::Create(context_owned.Pass());
3455 output_surface->InitializeAndSetContext3d(context_provider);
3456 resource_provider->InitializeGL();
3458 CheckCreateResource(ResourceProvider::GLTexture, resource_provider, context);
3461 TEST(ResourceProviderTest, BasicInitializeGLSoftware) {
3462 scoped_ptr<ContextSharedData> shared_data = ContextSharedData::Create();
3463 bool delegated_rendering = false;
3464 scoped_ptr<FakeOutputSurface> output_surface(
3465 FakeOutputSurface::CreateDeferredGL(
3466 scoped_ptr<SoftwareOutputDevice>(new SoftwareOutputDevice),
3467 delegated_rendering));
3468 FakeOutputSurfaceClient client(output_surface.get());
3469 EXPECT_TRUE(output_surface->BindToClient(&client));
3470 scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
3471 new TestSharedBitmapManager());
3472 scoped_ptr<ResourceProvider> resource_provider(
3473 ResourceProvider::Create(output_surface.get(),
3474 shared_bitmap_manager.get(),
3475 NULL,
3476 NULL,
3478 false,
3479 1));
3481 CheckCreateResource(ResourceProvider::Bitmap, resource_provider.get(), NULL);
3483 InitializeGLAndCheck(shared_data.get(),
3484 resource_provider.get(),
3485 output_surface.get());
3487 resource_provider->InitializeSoftware();
3488 output_surface->ReleaseGL();
3489 CheckCreateResource(ResourceProvider::Bitmap, resource_provider.get(), NULL);
3491 InitializeGLAndCheck(shared_data.get(),
3492 resource_provider.get(),
3493 output_surface.get());
3496 TEST_P(ResourceProviderTest, CompressedTextureETC1Allocate) {
3497 if (GetParam() != ResourceProvider::GLTexture)
3498 return;
3500 scoped_ptr<AllocationTrackingContext3D> context_owned(
3501 new AllocationTrackingContext3D);
3502 AllocationTrackingContext3D* context = context_owned.get();
3503 context_owned->set_support_compressed_texture_etc1(true);
3505 FakeOutputSurfaceClient output_surface_client;
3506 scoped_ptr<OutputSurface> output_surface(
3507 FakeOutputSurface::Create3d(context_owned.Pass()));
3508 CHECK(output_surface->BindToClient(&output_surface_client));
3510 gfx::Size size(4, 4);
3511 scoped_ptr<ResourceProvider> resource_provider(
3512 ResourceProvider::Create(output_surface.get(),
3513 shared_bitmap_manager_.get(),
3514 gpu_memory_buffer_manager_.get(),
3515 NULL,
3517 false,
3518 1));
3519 int texture_id = 123;
3521 ResourceProvider::ResourceId id = resource_provider->CreateResource(
3522 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, ETC1);
3523 EXPECT_NE(0u, id);
3524 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3525 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
3526 resource_provider->AllocateForTesting(id);
3528 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3529 resource_provider->DeleteResource(id);
3532 TEST_P(ResourceProviderTest, CompressedTextureETC1SetPixels) {
3533 if (GetParam() != ResourceProvider::GLTexture)
3534 return;
3536 scoped_ptr<AllocationTrackingContext3D> context_owned(
3537 new AllocationTrackingContext3D);
3538 AllocationTrackingContext3D* context = context_owned.get();
3539 context_owned->set_support_compressed_texture_etc1(true);
3541 FakeOutputSurfaceClient output_surface_client;
3542 scoped_ptr<OutputSurface> output_surface(
3543 FakeOutputSurface::Create3d(context_owned.Pass()));
3544 CHECK(output_surface->BindToClient(&output_surface_client));
3546 gfx::Size size(4, 4);
3547 scoped_ptr<ResourceProvider> resource_provider(
3548 ResourceProvider::Create(output_surface.get(),
3549 shared_bitmap_manager_.get(),
3550 gpu_memory_buffer_manager_.get(),
3551 NULL,
3553 false,
3554 1));
3555 int texture_id = 123;
3556 uint8_t pixels[8];
3558 ResourceProvider::ResourceId id = resource_provider->CreateResource(
3559 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, ETC1);
3560 EXPECT_NE(0u, id);
3561 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3562 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(3);
3563 EXPECT_CALL(*context,
3564 compressedTexImage2D(
3565 _, 0, _, size.width(), size.height(), _, _, _)).Times(1);
3566 resource_provider->SetPixels(
3567 id, pixels, gfx::Rect(size), gfx::Rect(size), gfx::Vector2d(0, 0));
3569 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3570 resource_provider->DeleteResource(id);
3573 INSTANTIATE_TEST_CASE_P(
3574 ResourceProviderTests,
3575 ResourceProviderTest,
3576 ::testing::Values(ResourceProvider::GLTexture, ResourceProvider::Bitmap));
3578 class TextureIdAllocationTrackingContext : public TestWebGraphicsContext3D {
3579 public:
3580 GLuint NextTextureId() override {
3581 base::AutoLock lock(namespace_->lock);
3582 return namespace_->next_texture_id++;
3584 void RetireTextureId(GLuint) override {}
3585 GLuint PeekTextureId() {
3586 base::AutoLock lock(namespace_->lock);
3587 return namespace_->next_texture_id;
3591 TEST(ResourceProviderTest, TextureAllocationChunkSize) {
3592 scoped_ptr<TextureIdAllocationTrackingContext> context_owned(
3593 new TextureIdAllocationTrackingContext);
3594 TextureIdAllocationTrackingContext* context = context_owned.get();
3596 FakeOutputSurfaceClient output_surface_client;
3597 scoped_ptr<OutputSurface> output_surface(
3598 FakeOutputSurface::Create3d(context_owned.Pass()));
3599 CHECK(output_surface->BindToClient(&output_surface_client));
3600 scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
3601 new TestSharedBitmapManager());
3603 gfx::Size size(1, 1);
3604 ResourceFormat format = RGBA_8888;
3607 size_t kTextureAllocationChunkSize = 1;
3608 scoped_ptr<ResourceProvider> resource_provider(
3609 ResourceProvider::Create(output_surface.get(),
3610 shared_bitmap_manager.get(),
3611 NULL,
3612 NULL,
3614 false,
3615 kTextureAllocationChunkSize));
3617 ResourceProvider::ResourceId id = resource_provider->CreateResource(
3618 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
3619 resource_provider->AllocateForTesting(id);
3620 Mock::VerifyAndClearExpectations(context);
3622 DCHECK_EQ(2u, context->PeekTextureId());
3623 resource_provider->DeleteResource(id);
3627 size_t kTextureAllocationChunkSize = 8;
3628 scoped_ptr<ResourceProvider> resource_provider(
3629 ResourceProvider::Create(output_surface.get(),
3630 shared_bitmap_manager.get(),
3631 NULL,
3632 NULL,
3634 false,
3635 kTextureAllocationChunkSize));
3637 ResourceProvider::ResourceId id = resource_provider->CreateResource(
3638 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
3639 resource_provider->AllocateForTesting(id);
3640 Mock::VerifyAndClearExpectations(context);
3642 DCHECK_EQ(10u, context->PeekTextureId());
3643 resource_provider->DeleteResource(id);
3647 } // namespace
3648 } // namespace cc