Revert 279472 "Mojo: Add mojo_shell_tests to the Linux bots."
[chromium-blink-merge.git] / cc / resources / resource_provider_unittest.cc
blob4bf9ec0565ec4bcfb59c97adab3d3f87749aaa00
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_shared_bitmap_manager.h"
23 #include "cc/test/test_texture.h"
24 #include "cc/test/test_web_graphics_context_3d.h"
25 #include "gpu/GLES2/gl2extchromium.h"
26 #include "testing/gmock/include/gmock/gmock.h"
27 #include "testing/gtest/include/gtest/gtest.h"
28 #include "third_party/khronos/GLES2/gl2.h"
29 #include "third_party/khronos/GLES2/gl2ext.h"
30 #include "ui/gfx/rect.h"
32 using testing::Mock;
33 using testing::NiceMock;
34 using testing::Return;
35 using testing::SetArgPointee;
36 using testing::StrictMock;
37 using testing::_;
39 namespace cc {
40 namespace {
42 static void EmptyReleaseCallback(uint32 sync_point, bool lost_resource) {}
44 static void SharedMemoryReleaseCallback(scoped_ptr<base::SharedMemory> memory,
45 uint32 sync_point,
46 bool lost_resource) {}
48 static void ReleaseTextureMailbox(uint32* release_sync_point,
49 bool* release_lost_resource,
50 uint32 sync_point,
51 bool lost_resource) {
52 *release_sync_point = sync_point;
53 *release_lost_resource = lost_resource;
56 static void ReleaseSharedMemoryCallback(
57 scoped_ptr<base::SharedMemory> shared_memory,
58 bool* release_called,
59 uint32* release_sync_point,
60 bool* lost_resource_result,
61 uint32 sync_point,
62 bool lost_resource) {
63 *release_called = true;
64 *release_sync_point = sync_point;
65 *lost_resource_result = lost_resource;
68 static scoped_ptr<base::SharedMemory> CreateAndFillSharedMemory(
69 const gfx::Size& size,
70 uint32_t value) {
71 scoped_ptr<base::SharedMemory> shared_memory(new base::SharedMemory);
72 CHECK(shared_memory->CreateAndMapAnonymous(4 * size.GetArea()));
73 uint32_t* pixels = reinterpret_cast<uint32_t*>(shared_memory->memory());
74 CHECK(pixels);
75 std::fill_n(pixels, size.GetArea(), value);
76 return shared_memory.Pass();
79 class TextureStateTrackingContext : public TestWebGraphicsContext3D {
80 public:
81 MOCK_METHOD2(bindTexture, void(GLenum target, GLuint texture));
82 MOCK_METHOD3(texParameteri, void(GLenum target, GLenum pname, GLint param));
83 MOCK_METHOD1(waitSyncPoint, void(GLuint sync_point));
84 MOCK_METHOD0(insertSyncPoint, GLuint(void));
85 MOCK_METHOD2(produceTextureCHROMIUM,
86 void(GLenum target, const GLbyte* mailbox));
87 MOCK_METHOD2(consumeTextureCHROMIUM,
88 void(GLenum target, const GLbyte* mailbox));
90 // Force all textures to be consecutive numbers starting at "1",
91 // so we easily can test for them.
92 virtual GLuint NextTextureId() OVERRIDE {
93 base::AutoLock lock(namespace_->lock);
94 return namespace_->next_texture_id++;
96 virtual void RetireTextureId(GLuint) OVERRIDE {}
99 // Shared data between multiple ResourceProviderContext. This contains mailbox
100 // contents as well as information about sync points.
101 class ContextSharedData {
102 public:
103 static scoped_ptr<ContextSharedData> Create() {
104 return make_scoped_ptr(new ContextSharedData());
107 uint32 InsertSyncPoint() { return next_sync_point_++; }
109 void GenMailbox(GLbyte* mailbox) {
110 memset(mailbox, 0, GL_MAILBOX_SIZE_CHROMIUM);
111 memcpy(mailbox, &next_mailbox_, sizeof(next_mailbox_));
112 ++next_mailbox_;
115 void ProduceTexture(const GLbyte* mailbox_name,
116 uint32 sync_point,
117 scoped_refptr<TestTexture> texture) {
118 unsigned mailbox = 0;
119 memcpy(&mailbox, mailbox_name, sizeof(mailbox));
120 ASSERT_TRUE(mailbox && mailbox < next_mailbox_);
121 textures_[mailbox] = texture;
122 ASSERT_LT(sync_point_for_mailbox_[mailbox], sync_point);
123 sync_point_for_mailbox_[mailbox] = sync_point;
126 scoped_refptr<TestTexture> ConsumeTexture(const GLbyte* mailbox_name,
127 uint32 sync_point) {
128 unsigned mailbox = 0;
129 memcpy(&mailbox, mailbox_name, sizeof(mailbox));
130 DCHECK(mailbox && mailbox < next_mailbox_);
132 // If the latest sync point the context has waited on is before the sync
133 // point for when the mailbox was set, pretend we never saw that
134 // ProduceTexture.
135 if (sync_point_for_mailbox_[mailbox] > sync_point) {
136 NOTREACHED();
137 return scoped_refptr<TestTexture>();
139 return textures_[mailbox];
142 private:
143 ContextSharedData() : next_sync_point_(1), next_mailbox_(1) {}
145 uint32 next_sync_point_;
146 unsigned next_mailbox_;
147 typedef base::hash_map<unsigned, scoped_refptr<TestTexture> > TextureMap;
148 TextureMap textures_;
149 base::hash_map<unsigned, uint32> sync_point_for_mailbox_;
152 class ResourceProviderContext : public TestWebGraphicsContext3D {
153 public:
154 static scoped_ptr<ResourceProviderContext> Create(
155 ContextSharedData* shared_data) {
156 return make_scoped_ptr(new ResourceProviderContext(shared_data));
159 virtual GLuint insertSyncPoint() OVERRIDE {
160 uint32 sync_point = shared_data_->InsertSyncPoint();
161 // Commit the produceTextureCHROMIUM calls at this point, so that
162 // they're associated with the sync point.
163 for (PendingProduceTextureList::iterator it =
164 pending_produce_textures_.begin();
165 it != pending_produce_textures_.end();
166 ++it) {
167 shared_data_->ProduceTexture(
168 (*it)->mailbox, sync_point, (*it)->texture);
170 pending_produce_textures_.clear();
171 return sync_point;
174 virtual void waitSyncPoint(GLuint sync_point) OVERRIDE {
175 last_waited_sync_point_ = std::max(sync_point, last_waited_sync_point_);
178 unsigned last_waited_sync_point() const { return last_waited_sync_point_; }
180 virtual void texStorage2DEXT(GLenum target,
181 GLint levels,
182 GLuint internalformat,
183 GLint width,
184 GLint height) OVERRIDE {
185 CheckTextureIsBound(target);
186 ASSERT_EQ(static_cast<unsigned>(GL_TEXTURE_2D), target);
187 ASSERT_EQ(1, levels);
188 GLenum format = GL_RGBA;
189 switch (internalformat) {
190 case GL_RGBA8_OES:
191 break;
192 case GL_BGRA8_EXT:
193 format = GL_BGRA_EXT;
194 break;
195 default:
196 NOTREACHED();
198 AllocateTexture(gfx::Size(width, height), format);
201 virtual void texImage2D(GLenum target,
202 GLint level,
203 GLenum internalformat,
204 GLsizei width,
205 GLsizei height,
206 GLint border,
207 GLenum format,
208 GLenum type,
209 const void* pixels) OVERRIDE {
210 CheckTextureIsBound(target);
211 ASSERT_EQ(static_cast<unsigned>(GL_TEXTURE_2D), target);
212 ASSERT_FALSE(level);
213 ASSERT_EQ(internalformat, format);
214 ASSERT_FALSE(border);
215 ASSERT_EQ(static_cast<unsigned>(GL_UNSIGNED_BYTE), type);
216 AllocateTexture(gfx::Size(width, height), format);
217 if (pixels)
218 SetPixels(0, 0, width, height, pixels);
221 virtual void texSubImage2D(GLenum target,
222 GLint level,
223 GLint xoffset,
224 GLint yoffset,
225 GLsizei width,
226 GLsizei height,
227 GLenum format,
228 GLenum type,
229 const void* pixels) OVERRIDE {
230 CheckTextureIsBound(target);
231 ASSERT_EQ(static_cast<unsigned>(GL_TEXTURE_2D), target);
232 ASSERT_FALSE(level);
233 ASSERT_EQ(static_cast<unsigned>(GL_UNSIGNED_BYTE), type);
235 base::AutoLock lock_for_texture_access(namespace_->lock);
236 ASSERT_EQ(GLDataFormat(BoundTexture(target)->format), format);
238 ASSERT_TRUE(pixels);
239 SetPixels(xoffset, yoffset, width, height, pixels);
242 virtual void genMailboxCHROMIUM(GLbyte* mailbox) OVERRIDE {
243 return shared_data_->GenMailbox(mailbox);
246 virtual void produceTextureCHROMIUM(GLenum target,
247 const GLbyte* mailbox) OVERRIDE {
248 CheckTextureIsBound(target);
250 // Delay moving the texture into the mailbox until the next
251 // InsertSyncPoint, so that it is not visible to other contexts that
252 // haven't waited on that sync point.
253 scoped_ptr<PendingProduceTexture> pending(new PendingProduceTexture);
254 memcpy(pending->mailbox, mailbox, sizeof(pending->mailbox));
255 base::AutoLock lock_for_texture_access(namespace_->lock);
256 pending->texture = BoundTexture(target);
257 pending_produce_textures_.push_back(pending.Pass());
260 virtual void consumeTextureCHROMIUM(GLenum target,
261 const GLbyte* mailbox) OVERRIDE {
262 CheckTextureIsBound(target);
263 base::AutoLock lock_for_texture_access(namespace_->lock);
264 scoped_refptr<TestTexture> texture =
265 shared_data_->ConsumeTexture(mailbox, last_waited_sync_point_);
266 namespace_->textures.Replace(BoundTextureId(target), texture);
269 void GetPixels(const gfx::Size& size,
270 ResourceFormat format,
271 uint8_t* pixels) {
272 CheckTextureIsBound(GL_TEXTURE_2D);
273 base::AutoLock lock_for_texture_access(namespace_->lock);
274 scoped_refptr<TestTexture> texture = BoundTexture(GL_TEXTURE_2D);
275 ASSERT_EQ(texture->size, size);
276 ASSERT_EQ(texture->format, format);
277 memcpy(pixels, texture->data.get(), TextureSizeBytes(size, format));
280 protected:
281 explicit ResourceProviderContext(ContextSharedData* shared_data)
282 : shared_data_(shared_data),
283 last_waited_sync_point_(0) {}
285 private:
286 void AllocateTexture(const gfx::Size& size, GLenum format) {
287 CheckTextureIsBound(GL_TEXTURE_2D);
288 ResourceFormat texture_format = RGBA_8888;
289 switch (format) {
290 case GL_RGBA:
291 texture_format = RGBA_8888;
292 break;
293 case GL_BGRA_EXT:
294 texture_format = BGRA_8888;
295 break;
297 base::AutoLock lock_for_texture_access(namespace_->lock);
298 BoundTexture(GL_TEXTURE_2D)->Reallocate(size, texture_format);
301 void SetPixels(int xoffset,
302 int yoffset,
303 int width,
304 int height,
305 const void* pixels) {
306 CheckTextureIsBound(GL_TEXTURE_2D);
307 base::AutoLock lock_for_texture_access(namespace_->lock);
308 scoped_refptr<TestTexture> texture = BoundTexture(GL_TEXTURE_2D);
309 ASSERT_TRUE(texture->data.get());
310 ASSERT_TRUE(xoffset >= 0 && xoffset + width <= texture->size.width());
311 ASSERT_TRUE(yoffset >= 0 && yoffset + height <= texture->size.height());
312 ASSERT_TRUE(pixels);
313 size_t in_pitch = TextureSizeBytes(gfx::Size(width, 1), texture->format);
314 size_t out_pitch =
315 TextureSizeBytes(gfx::Size(texture->size.width(), 1), texture->format);
316 uint8_t* dest = texture->data.get() + yoffset * out_pitch +
317 TextureSizeBytes(gfx::Size(xoffset, 1), texture->format);
318 const uint8_t* src = static_cast<const uint8_t*>(pixels);
319 for (int i = 0; i < height; ++i) {
320 memcpy(dest, src, in_pitch);
321 dest += out_pitch;
322 src += in_pitch;
326 struct PendingProduceTexture {
327 GLbyte mailbox[GL_MAILBOX_SIZE_CHROMIUM];
328 scoped_refptr<TestTexture> texture;
330 typedef ScopedPtrDeque<PendingProduceTexture> PendingProduceTextureList;
331 ContextSharedData* shared_data_;
332 GLuint last_waited_sync_point_;
333 PendingProduceTextureList pending_produce_textures_;
336 void GetResourcePixels(ResourceProvider* resource_provider,
337 ResourceProviderContext* context,
338 ResourceProvider::ResourceId id,
339 const gfx::Size& size,
340 ResourceFormat format,
341 uint8_t* pixels) {
342 switch (resource_provider->default_resource_type()) {
343 case ResourceProvider::GLTexture: {
344 ResourceProvider::ScopedReadLockGL lock_gl(resource_provider, id);
345 ASSERT_NE(0U, lock_gl.texture_id());
346 context->bindTexture(GL_TEXTURE_2D, lock_gl.texture_id());
347 context->GetPixels(size, format, pixels);
348 break;
350 case ResourceProvider::Bitmap: {
351 ResourceProvider::ScopedReadLockSoftware lock_software(resource_provider,
352 id);
353 memcpy(pixels,
354 lock_software.sk_bitmap()->getPixels(),
355 lock_software.sk_bitmap()->getSize());
356 break;
358 case ResourceProvider::InvalidType:
359 NOTREACHED();
360 break;
364 class ResourceProviderTest
365 : public testing::TestWithParam<ResourceProvider::ResourceType> {
366 public:
367 ResourceProviderTest()
368 : shared_data_(ContextSharedData::Create()),
369 context3d_(NULL),
370 child_context_(NULL) {
371 switch (GetParam()) {
372 case ResourceProvider::GLTexture: {
373 scoped_ptr<ResourceProviderContext> context3d(
374 ResourceProviderContext::Create(shared_data_.get()));
375 context3d_ = context3d.get();
377 scoped_refptr<TestContextProvider> context_provider =
378 TestContextProvider::Create(
379 context3d.PassAs<TestWebGraphicsContext3D>());
381 output_surface_ = FakeOutputSurface::Create3d(context_provider);
383 scoped_ptr<ResourceProviderContext> child_context_owned =
384 ResourceProviderContext::Create(shared_data_.get());
385 child_context_ = child_context_owned.get();
386 child_output_surface_ = FakeOutputSurface::Create3d(
387 child_context_owned.PassAs<TestWebGraphicsContext3D>());
388 break;
390 case ResourceProvider::Bitmap:
391 output_surface_ = FakeOutputSurface::CreateSoftware(
392 make_scoped_ptr(new SoftwareOutputDevice));
393 child_output_surface_ = FakeOutputSurface::CreateSoftware(
394 make_scoped_ptr(new SoftwareOutputDevice));
395 break;
396 case ResourceProvider::InvalidType:
397 NOTREACHED();
398 break;
400 CHECK(output_surface_->BindToClient(&output_surface_client_));
401 CHECK(child_output_surface_->BindToClient(&child_output_surface_client_));
403 shared_bitmap_manager_.reset(new TestSharedBitmapManager());
405 resource_provider_ = ResourceProvider::Create(
406 output_surface_.get(), shared_bitmap_manager_.get(), 0, false, 1,
407 false);
408 child_resource_provider_ = ResourceProvider::Create(
409 child_output_surface_.get(),
410 shared_bitmap_manager_.get(),
412 false,
414 false);
417 static void CollectResources(ReturnedResourceArray* array,
418 const ReturnedResourceArray& returned) {
419 array->insert(array->end(), returned.begin(), returned.end());
422 static ReturnCallback GetReturnCallback(ReturnedResourceArray* array) {
423 return base::Bind(&ResourceProviderTest::CollectResources, array);
426 static void SetResourceFilter(ResourceProvider* resource_provider,
427 ResourceProvider::ResourceId id,
428 GLenum filter) {
429 ResourceProvider::ScopedSamplerGL sampler(
430 resource_provider, id, GL_TEXTURE_2D, filter);
433 ResourceProviderContext* context() { return context3d_; }
435 ResourceProvider::ResourceId CreateChildMailbox(uint32* release_sync_point,
436 bool* lost_resource,
437 bool* release_called,
438 uint32* sync_point) {
439 if (GetParam() == ResourceProvider::GLTexture) {
440 unsigned texture = child_context_->createTexture();
441 gpu::Mailbox gpu_mailbox;
442 child_context_->bindTexture(GL_TEXTURE_2D, texture);
443 child_context_->genMailboxCHROMIUM(gpu_mailbox.name);
444 child_context_->produceTextureCHROMIUM(GL_TEXTURE_2D, gpu_mailbox.name);
445 *sync_point = child_context_->insertSyncPoint();
446 EXPECT_LT(0u, *sync_point);
448 scoped_ptr<base::SharedMemory> shared_memory;
449 scoped_ptr<SingleReleaseCallback> callback =
450 SingleReleaseCallback::Create(base::Bind(ReleaseSharedMemoryCallback,
451 base::Passed(&shared_memory),
452 release_called,
453 release_sync_point,
454 lost_resource));
455 return child_resource_provider_->CreateResourceFromTextureMailbox(
456 TextureMailbox(gpu_mailbox, GL_TEXTURE_2D, *sync_point),
457 callback.Pass());
458 } else {
459 gfx::Size size(64, 64);
460 scoped_ptr<base::SharedMemory> shared_memory(
461 CreateAndFillSharedMemory(size, 0));
463 base::SharedMemory* shared_memory_ptr = shared_memory.get();
464 scoped_ptr<SingleReleaseCallback> callback =
465 SingleReleaseCallback::Create(base::Bind(ReleaseSharedMemoryCallback,
466 base::Passed(&shared_memory),
467 release_called,
468 release_sync_point,
469 lost_resource));
470 return child_resource_provider_->CreateResourceFromTextureMailbox(
471 TextureMailbox(shared_memory_ptr, size), callback.Pass());
475 protected:
476 scoped_ptr<ContextSharedData> shared_data_;
477 ResourceProviderContext* context3d_;
478 ResourceProviderContext* child_context_;
479 FakeOutputSurfaceClient output_surface_client_;
480 FakeOutputSurfaceClient child_output_surface_client_;
481 scoped_ptr<OutputSurface> output_surface_;
482 scoped_ptr<OutputSurface> child_output_surface_;
483 scoped_ptr<ResourceProvider> resource_provider_;
484 scoped_ptr<ResourceProvider> child_resource_provider_;
485 scoped_ptr<TestSharedBitmapManager> shared_bitmap_manager_;
488 void CheckCreateResource(ResourceProvider::ResourceType expected_default_type,
489 ResourceProvider* resource_provider,
490 ResourceProviderContext* context) {
491 DCHECK_EQ(expected_default_type, resource_provider->default_resource_type());
493 gfx::Size size(1, 1);
494 ResourceFormat format = RGBA_8888;
495 size_t pixel_size = TextureSizeBytes(size, format);
496 ASSERT_EQ(4U, pixel_size);
498 ResourceProvider::ResourceId id = resource_provider->CreateResource(
499 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
500 EXPECT_EQ(1, static_cast<int>(resource_provider->num_resources()));
501 if (expected_default_type == ResourceProvider::GLTexture)
502 EXPECT_EQ(0u, context->NumTextures());
504 uint8_t data[4] = { 1, 2, 3, 4 };
505 gfx::Rect rect(size);
506 resource_provider->SetPixels(id, data, rect, rect, gfx::Vector2d());
507 if (expected_default_type == ResourceProvider::GLTexture)
508 EXPECT_EQ(1u, context->NumTextures());
510 uint8_t result[4] = { 0 };
511 GetResourcePixels(resource_provider, context, id, size, format, result);
512 EXPECT_EQ(0, memcmp(data, result, pixel_size));
514 resource_provider->DeleteResource(id);
515 EXPECT_EQ(0, static_cast<int>(resource_provider->num_resources()));
516 if (expected_default_type == ResourceProvider::GLTexture)
517 EXPECT_EQ(0u, context->NumTextures());
520 TEST_P(ResourceProviderTest, Basic) {
521 CheckCreateResource(GetParam(), resource_provider_.get(), context());
524 TEST_P(ResourceProviderTest, Upload) {
525 gfx::Size size(2, 2);
526 ResourceFormat format = RGBA_8888;
527 size_t pixel_size = TextureSizeBytes(size, format);
528 ASSERT_EQ(16U, pixel_size);
530 ResourceProvider::ResourceId id = resource_provider_->CreateResource(
531 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
533 uint8_t image[16] = { 0 };
534 gfx::Rect image_rect(size);
535 resource_provider_->SetPixels(
536 id, image, image_rect, image_rect, gfx::Vector2d());
538 for (uint8_t i = 0; i < pixel_size; ++i)
539 image[i] = i;
541 uint8_t result[16] = { 0 };
543 gfx::Rect source_rect(0, 0, 1, 1);
544 gfx::Vector2d dest_offset(0, 0);
545 resource_provider_->SetPixels(
546 id, image, image_rect, source_rect, dest_offset);
548 uint8_t expected[16] = { 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
549 GetResourcePixels(
550 resource_provider_.get(), context(), id, size, format, result);
551 EXPECT_EQ(0, memcmp(expected, result, pixel_size));
554 gfx::Rect source_rect(0, 0, 1, 1);
555 gfx::Vector2d dest_offset(1, 1);
556 resource_provider_->SetPixels(
557 id, image, image_rect, source_rect, dest_offset);
559 uint8_t expected[16] = { 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3 };
560 GetResourcePixels(
561 resource_provider_.get(), context(), id, size, format, result);
562 EXPECT_EQ(0, memcmp(expected, result, pixel_size));
565 gfx::Rect source_rect(1, 0, 1, 1);
566 gfx::Vector2d dest_offset(0, 1);
567 resource_provider_->SetPixels(
568 id, image, image_rect, source_rect, dest_offset);
570 uint8_t expected[16] = { 0, 1, 2, 3, 0, 0, 0, 0, 4, 5, 6, 7, 0, 1, 2, 3 };
571 GetResourcePixels(
572 resource_provider_.get(), context(), id, size, format, result);
573 EXPECT_EQ(0, memcmp(expected, result, pixel_size));
576 gfx::Rect offset_image_rect(gfx::Point(100, 100), size);
577 gfx::Rect source_rect(100, 100, 1, 1);
578 gfx::Vector2d dest_offset(1, 0);
579 resource_provider_->SetPixels(
580 id, image, offset_image_rect, source_rect, dest_offset);
582 uint8_t expected[16] = { 0, 1, 2, 3, 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3 };
583 GetResourcePixels(
584 resource_provider_.get(), context(), id, size, format, result);
585 EXPECT_EQ(0, memcmp(expected, result, pixel_size));
588 resource_provider_->DeleteResource(id);
591 TEST_P(ResourceProviderTest, TransferGLResources) {
592 if (GetParam() != ResourceProvider::GLTexture)
593 return;
594 gfx::Size size(1, 1);
595 ResourceFormat format = RGBA_8888;
596 size_t pixel_size = TextureSizeBytes(size, format);
597 ASSERT_EQ(4U, pixel_size);
599 ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource(
600 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
601 uint8_t data1[4] = { 1, 2, 3, 4 };
602 gfx::Rect rect(size);
603 child_resource_provider_->SetPixels(id1, data1, rect, rect, gfx::Vector2d());
605 ResourceProvider::ResourceId id2 = child_resource_provider_->CreateResource(
606 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
607 uint8_t data2[4] = { 5, 5, 5, 5 };
608 child_resource_provider_->SetPixels(id2, data2, rect, rect, gfx::Vector2d());
610 ResourceProvider::ResourceId id3 = child_resource_provider_->CreateResource(
611 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
612 child_resource_provider_->MapImageRasterBuffer(id3);
613 child_resource_provider_->UnmapImageRasterBuffer(id3);
615 GLuint external_texture_id = child_context_->createExternalTexture();
616 child_context_->bindTexture(GL_TEXTURE_EXTERNAL_OES, external_texture_id);
618 gpu::Mailbox external_mailbox;
619 child_context_->genMailboxCHROMIUM(external_mailbox.name);
620 child_context_->produceTextureCHROMIUM(GL_TEXTURE_EXTERNAL_OES,
621 external_mailbox.name);
622 const GLuint external_sync_point = child_context_->insertSyncPoint();
623 ResourceProvider::ResourceId id4 =
624 child_resource_provider_->CreateResourceFromTextureMailbox(
625 TextureMailbox(
626 external_mailbox, GL_TEXTURE_EXTERNAL_OES, external_sync_point),
627 SingleReleaseCallback::Create(base::Bind(&EmptyReleaseCallback)));
629 ReturnedResourceArray returned_to_child;
630 int child_id =
631 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
633 // Transfer some resources to the parent.
634 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
635 resource_ids_to_transfer.push_back(id1);
636 resource_ids_to_transfer.push_back(id2);
637 resource_ids_to_transfer.push_back(id3);
638 resource_ids_to_transfer.push_back(id4);
639 TransferableResourceArray list;
640 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
641 &list);
642 ASSERT_EQ(4u, list.size());
643 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
644 EXPECT_NE(0u, list[1].mailbox_holder.sync_point);
645 EXPECT_EQ(list[0].mailbox_holder.sync_point,
646 list[1].mailbox_holder.sync_point);
647 EXPECT_NE(0u, list[2].mailbox_holder.sync_point);
648 EXPECT_EQ(list[0].mailbox_holder.sync_point,
649 list[2].mailbox_holder.sync_point);
650 EXPECT_EQ(external_sync_point, list[3].mailbox_holder.sync_point);
651 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
652 list[0].mailbox_holder.texture_target);
653 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
654 list[1].mailbox_holder.texture_target);
655 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
656 list[2].mailbox_holder.texture_target);
657 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_EXTERNAL_OES),
658 list[3].mailbox_holder.texture_target);
659 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
660 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
661 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
662 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id4));
663 resource_provider_->ReceiveFromChild(child_id, list);
664 EXPECT_NE(list[0].mailbox_holder.sync_point,
665 context3d_->last_waited_sync_point());
667 ResourceProvider::ScopedReadLockGL lock(resource_provider_.get(),
668 list[0].id);
670 EXPECT_EQ(list[0].mailbox_holder.sync_point,
671 context3d_->last_waited_sync_point());
672 resource_provider_->DeclareUsedResourcesFromChild(child_id,
673 resource_ids_to_transfer);
676 EXPECT_EQ(4u, resource_provider_->num_resources());
677 ResourceProvider::ResourceIdMap resource_map =
678 resource_provider_->GetChildToParentMap(child_id);
679 ResourceProvider::ResourceId mapped_id1 = resource_map[id1];
680 ResourceProvider::ResourceId mapped_id2 = resource_map[id2];
681 ResourceProvider::ResourceId mapped_id3 = resource_map[id3];
682 ResourceProvider::ResourceId mapped_id4 = resource_map[id4];
683 EXPECT_NE(0u, mapped_id1);
684 EXPECT_NE(0u, mapped_id2);
685 EXPECT_NE(0u, mapped_id3);
686 EXPECT_NE(0u, mapped_id4);
687 EXPECT_FALSE(resource_provider_->InUseByConsumer(id1));
688 EXPECT_FALSE(resource_provider_->InUseByConsumer(id2));
689 EXPECT_FALSE(resource_provider_->InUseByConsumer(id3));
690 EXPECT_FALSE(resource_provider_->InUseByConsumer(id4));
692 uint8_t result[4] = { 0 };
693 GetResourcePixels(
694 resource_provider_.get(), context(), mapped_id1, size, format, result);
695 EXPECT_EQ(0, memcmp(data1, result, pixel_size));
697 GetResourcePixels(
698 resource_provider_.get(), context(), mapped_id2, size, format, result);
699 EXPECT_EQ(0, memcmp(data2, result, pixel_size));
702 // Check that transfering again the same resource from the child to the
703 // parent works.
704 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
705 resource_ids_to_transfer.push_back(id1);
706 resource_ids_to_transfer.push_back(id2);
707 resource_ids_to_transfer.push_back(id3);
708 TransferableResourceArray list;
709 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
710 &list);
711 EXPECT_EQ(3u, list.size());
712 EXPECT_EQ(id1, list[0].id);
713 EXPECT_EQ(id2, list[1].id);
714 EXPECT_EQ(id3, list[2].id);
715 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
716 list[0].mailbox_holder.texture_target);
717 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
718 list[1].mailbox_holder.texture_target);
719 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
720 list[2].mailbox_holder.texture_target);
721 ReturnedResourceArray returned;
722 TransferableResource::ReturnResources(list, &returned);
723 child_resource_provider_->ReceiveReturnsFromParent(returned);
724 // ids were exported twice, we returned them only once, they should still
725 // be in-use.
726 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
727 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
728 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
731 EXPECT_EQ(0u, returned_to_child.size());
733 // Transfer resources back from the parent to the child. Set no resources as
734 // being in use.
735 ResourceProvider::ResourceIdArray no_resources;
736 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
738 ASSERT_EQ(4u, returned_to_child.size());
739 EXPECT_NE(0u, returned_to_child[0].sync_point);
740 EXPECT_NE(0u, returned_to_child[1].sync_point);
741 EXPECT_NE(0u, returned_to_child[2].sync_point);
742 EXPECT_NE(0u, returned_to_child[3].sync_point);
743 EXPECT_FALSE(returned_to_child[0].lost);
744 EXPECT_FALSE(returned_to_child[1].lost);
745 EXPECT_FALSE(returned_to_child[2].lost);
746 EXPECT_FALSE(returned_to_child[3].lost);
747 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
748 returned_to_child.clear();
750 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id1));
751 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id2));
752 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id3));
753 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id4));
756 ResourceProvider::ScopedReadLockGL lock(child_resource_provider_.get(),
757 id1);
758 ASSERT_NE(0U, lock.texture_id());
759 child_context_->bindTexture(GL_TEXTURE_2D, lock.texture_id());
760 child_context_->GetPixels(size, format, result);
761 EXPECT_EQ(0, memcmp(data1, result, pixel_size));
764 ResourceProvider::ScopedReadLockGL lock(child_resource_provider_.get(),
765 id2);
766 ASSERT_NE(0U, lock.texture_id());
767 child_context_->bindTexture(GL_TEXTURE_2D, lock.texture_id());
768 child_context_->GetPixels(size, format, result);
769 EXPECT_EQ(0, memcmp(data2, result, pixel_size));
772 ResourceProvider::ScopedReadLockGL lock(child_resource_provider_.get(),
773 id3);
774 ASSERT_NE(0U, lock.texture_id());
775 child_context_->bindTexture(GL_TEXTURE_2D, lock.texture_id());
778 // Transfer resources to the parent again.
779 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
780 resource_ids_to_transfer.push_back(id1);
781 resource_ids_to_transfer.push_back(id2);
782 resource_ids_to_transfer.push_back(id3);
783 resource_ids_to_transfer.push_back(id4);
784 TransferableResourceArray list;
785 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
786 &list);
787 ASSERT_EQ(4u, list.size());
788 EXPECT_EQ(id1, list[0].id);
789 EXPECT_EQ(id2, list[1].id);
790 EXPECT_EQ(id3, list[2].id);
791 EXPECT_EQ(id4, list[3].id);
792 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
793 EXPECT_NE(0u, list[1].mailbox_holder.sync_point);
794 EXPECT_NE(0u, list[2].mailbox_holder.sync_point);
795 EXPECT_NE(0u, list[3].mailbox_holder.sync_point);
796 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
797 list[0].mailbox_holder.texture_target);
798 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
799 list[1].mailbox_holder.texture_target);
800 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
801 list[2].mailbox_holder.texture_target);
802 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_EXTERNAL_OES),
803 list[3].mailbox_holder.texture_target);
804 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
805 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
806 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
807 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id4));
808 resource_provider_->ReceiveFromChild(child_id, list);
809 resource_provider_->DeclareUsedResourcesFromChild(child_id,
810 resource_ids_to_transfer);
813 EXPECT_EQ(0u, returned_to_child.size());
815 EXPECT_EQ(4u, resource_provider_->num_resources());
816 resource_provider_->DestroyChild(child_id);
817 EXPECT_EQ(0u, resource_provider_->num_resources());
819 ASSERT_EQ(4u, returned_to_child.size());
820 EXPECT_NE(0u, returned_to_child[0].sync_point);
821 EXPECT_NE(0u, returned_to_child[1].sync_point);
822 EXPECT_NE(0u, returned_to_child[2].sync_point);
823 EXPECT_NE(0u, returned_to_child[3].sync_point);
824 EXPECT_FALSE(returned_to_child[0].lost);
825 EXPECT_FALSE(returned_to_child[1].lost);
826 EXPECT_FALSE(returned_to_child[2].lost);
827 EXPECT_FALSE(returned_to_child[3].lost);
830 TEST_P(ResourceProviderTest, ReadLockCountStopsReturnToChildOrDelete) {
831 if (GetParam() != ResourceProvider::GLTexture)
832 return;
833 gfx::Size size(1, 1);
834 ResourceFormat format = RGBA_8888;
836 ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource(
837 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
838 uint8_t data1[4] = {1, 2, 3, 4};
839 gfx::Rect rect(size);
840 child_resource_provider_->SetPixels(id1, data1, rect, rect, gfx::Vector2d());
842 ReturnedResourceArray returned_to_child;
843 int child_id =
844 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
846 // Transfer some resources to the parent.
847 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
848 resource_ids_to_transfer.push_back(id1);
849 TransferableResourceArray list;
850 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
851 &list);
852 ASSERT_EQ(1u, list.size());
853 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
855 resource_provider_->ReceiveFromChild(child_id, list);
857 ResourceProvider::ScopedReadLockGL lock(resource_provider_.get(),
858 list[0].id);
860 resource_provider_->DeclareUsedResourcesFromChild(
861 child_id, ResourceProvider::ResourceIdArray());
862 EXPECT_EQ(0u, returned_to_child.size());
865 EXPECT_EQ(1u, returned_to_child.size());
866 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
869 ResourceProvider::ScopedReadLockGL lock(child_resource_provider_.get(),
870 id1);
871 child_resource_provider_->DeleteResource(id1);
872 EXPECT_EQ(1u, child_resource_provider_->num_resources());
873 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
876 EXPECT_EQ(0u, child_resource_provider_->num_resources());
877 resource_provider_->DestroyChild(child_id);
880 TEST_P(ResourceProviderTest, TransferSoftwareResources) {
881 if (GetParam() != ResourceProvider::Bitmap)
882 return;
884 gfx::Size size(1, 1);
885 ResourceFormat format = RGBA_8888;
886 size_t pixel_size = TextureSizeBytes(size, format);
887 ASSERT_EQ(4U, pixel_size);
889 ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource(
890 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
891 uint8_t data1[4] = { 1, 2, 3, 4 };
892 gfx::Rect rect(size);
893 child_resource_provider_->SetPixels(id1, data1, rect, rect, gfx::Vector2d());
895 ResourceProvider::ResourceId id2 = child_resource_provider_->CreateResource(
896 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
897 uint8_t data2[4] = { 5, 5, 5, 5 };
898 child_resource_provider_->SetPixels(id2, data2, rect, rect, gfx::Vector2d());
900 ResourceProvider::ResourceId id3 = child_resource_provider_->CreateResource(
901 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
902 uint8_t data3[4] = { 6, 7, 8, 9 };
903 SkImageInfo info = SkImageInfo::MakeN32Premul(size.width(), size.height());
904 SkCanvas* raster_canvas = child_resource_provider_->MapImageRasterBuffer(id3);
905 raster_canvas->writePixels(info, data3, info.minRowBytes(), 0, 0);
906 child_resource_provider_->UnmapImageRasterBuffer(id3);
908 scoped_ptr<base::SharedMemory> shared_memory(new base::SharedMemory());
909 shared_memory->CreateAndMapAnonymous(1);
910 base::SharedMemory* shared_memory_ptr = shared_memory.get();
911 ResourceProvider::ResourceId id4 =
912 child_resource_provider_->CreateResourceFromTextureMailbox(
913 TextureMailbox(shared_memory_ptr, gfx::Size(1, 1)),
914 SingleReleaseCallback::Create(base::Bind(
915 &SharedMemoryReleaseCallback, base::Passed(&shared_memory))));
917 ReturnedResourceArray returned_to_child;
918 int child_id =
919 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
921 // Transfer some resources to the parent.
922 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
923 resource_ids_to_transfer.push_back(id1);
924 resource_ids_to_transfer.push_back(id2);
925 resource_ids_to_transfer.push_back(id3);
926 resource_ids_to_transfer.push_back(id4);
927 TransferableResourceArray list;
928 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
929 &list);
930 ASSERT_EQ(4u, list.size());
931 EXPECT_EQ(0u, list[0].mailbox_holder.sync_point);
932 EXPECT_EQ(0u, list[1].mailbox_holder.sync_point);
933 EXPECT_EQ(0u, list[2].mailbox_holder.sync_point);
934 EXPECT_EQ(0u, list[3].mailbox_holder.sync_point);
935 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
936 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
937 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
938 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id4));
939 resource_provider_->ReceiveFromChild(child_id, list);
940 resource_provider_->DeclareUsedResourcesFromChild(child_id,
941 resource_ids_to_transfer);
944 EXPECT_EQ(4u, resource_provider_->num_resources());
945 ResourceProvider::ResourceIdMap resource_map =
946 resource_provider_->GetChildToParentMap(child_id);
947 ResourceProvider::ResourceId mapped_id1 = resource_map[id1];
948 ResourceProvider::ResourceId mapped_id2 = resource_map[id2];
949 ResourceProvider::ResourceId mapped_id3 = resource_map[id3];
950 ResourceProvider::ResourceId mapped_id4 = resource_map[id4];
951 EXPECT_NE(0u, mapped_id1);
952 EXPECT_NE(0u, mapped_id2);
953 EXPECT_NE(0u, mapped_id3);
954 EXPECT_NE(0u, mapped_id4);
955 EXPECT_FALSE(resource_provider_->InUseByConsumer(id1));
956 EXPECT_FALSE(resource_provider_->InUseByConsumer(id2));
957 EXPECT_FALSE(resource_provider_->InUseByConsumer(id3));
958 EXPECT_FALSE(resource_provider_->InUseByConsumer(id4));
960 uint8_t result[4] = { 0 };
961 GetResourcePixels(
962 resource_provider_.get(), context(), mapped_id1, size, format, result);
963 EXPECT_EQ(0, memcmp(data1, result, pixel_size));
965 GetResourcePixels(
966 resource_provider_.get(), context(), mapped_id2, size, format, result);
967 EXPECT_EQ(0, memcmp(data2, result, pixel_size));
969 GetResourcePixels(
970 resource_provider_.get(), context(), mapped_id3, size, format, result);
971 EXPECT_EQ(0, memcmp(data3, result, pixel_size));
974 // Check that transfering again the same resource from the child to the
975 // parent works.
976 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
977 resource_ids_to_transfer.push_back(id1);
978 resource_ids_to_transfer.push_back(id2);
979 resource_ids_to_transfer.push_back(id3);
980 TransferableResourceArray list;
981 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
982 &list);
983 EXPECT_EQ(3u, list.size());
984 EXPECT_EQ(id1, list[0].id);
985 EXPECT_EQ(id2, list[1].id);
986 EXPECT_EQ(id3, list[2].id);
987 ReturnedResourceArray returned;
988 TransferableResource::ReturnResources(list, &returned);
989 child_resource_provider_->ReceiveReturnsFromParent(returned);
990 // ids were exported twice, we returned them only once, they should still
991 // be in-use.
992 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
993 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
994 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
997 EXPECT_EQ(0u, returned_to_child.size());
999 // Transfer resources back from the parent to the child. Set no resources as
1000 // being in use.
1001 ResourceProvider::ResourceIdArray no_resources;
1002 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
1004 ASSERT_EQ(4u, returned_to_child.size());
1005 EXPECT_EQ(0u, returned_to_child[0].sync_point);
1006 EXPECT_EQ(0u, returned_to_child[1].sync_point);
1007 EXPECT_EQ(0u, returned_to_child[2].sync_point);
1008 EXPECT_EQ(0u, returned_to_child[3].sync_point);
1009 std::set<ResourceProvider::ResourceId> expected_ids;
1010 expected_ids.insert(id1);
1011 expected_ids.insert(id2);
1012 expected_ids.insert(id3);
1013 expected_ids.insert(id4);
1014 std::set<ResourceProvider::ResourceId> returned_ids;
1015 for (unsigned i = 0; i < 4; i++)
1016 returned_ids.insert(returned_to_child[i].id);
1017 EXPECT_EQ(expected_ids, returned_ids);
1018 EXPECT_FALSE(returned_to_child[0].lost);
1019 EXPECT_FALSE(returned_to_child[1].lost);
1020 EXPECT_FALSE(returned_to_child[2].lost);
1021 EXPECT_FALSE(returned_to_child[3].lost);
1022 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
1023 returned_to_child.clear();
1025 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id1));
1026 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id2));
1027 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id3));
1028 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id4));
1031 ResourceProvider::ScopedReadLockSoftware lock(
1032 child_resource_provider_.get(), id1);
1033 const SkBitmap* sk_bitmap = lock.sk_bitmap();
1034 EXPECT_EQ(sk_bitmap->width(), size.width());
1035 EXPECT_EQ(sk_bitmap->height(), size.height());
1036 EXPECT_EQ(0, memcmp(data1, sk_bitmap->getPixels(), pixel_size));
1039 ResourceProvider::ScopedReadLockSoftware lock(
1040 child_resource_provider_.get(), id2);
1041 const SkBitmap* sk_bitmap = lock.sk_bitmap();
1042 EXPECT_EQ(sk_bitmap->width(), size.width());
1043 EXPECT_EQ(sk_bitmap->height(), size.height());
1044 EXPECT_EQ(0, memcmp(data2, sk_bitmap->getPixels(), pixel_size));
1047 ResourceProvider::ScopedReadLockSoftware lock(
1048 child_resource_provider_.get(), id3);
1049 const SkBitmap* sk_bitmap = lock.sk_bitmap();
1050 EXPECT_EQ(sk_bitmap->width(), size.width());
1051 EXPECT_EQ(sk_bitmap->height(), size.height());
1052 EXPECT_EQ(0, memcmp(data3, sk_bitmap->getPixels(), pixel_size));
1055 // Transfer resources to the parent again.
1056 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1057 resource_ids_to_transfer.push_back(id1);
1058 resource_ids_to_transfer.push_back(id2);
1059 resource_ids_to_transfer.push_back(id3);
1060 resource_ids_to_transfer.push_back(id4);
1061 TransferableResourceArray list;
1062 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1063 &list);
1064 ASSERT_EQ(4u, list.size());
1065 EXPECT_EQ(id1, list[0].id);
1066 EXPECT_EQ(id2, list[1].id);
1067 EXPECT_EQ(id3, list[2].id);
1068 EXPECT_EQ(id4, list[3].id);
1069 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1070 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
1071 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
1072 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id4));
1073 resource_provider_->ReceiveFromChild(child_id, list);
1074 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1075 resource_ids_to_transfer);
1078 EXPECT_EQ(0u, returned_to_child.size());
1080 EXPECT_EQ(4u, resource_provider_->num_resources());
1081 resource_provider_->DestroyChild(child_id);
1082 EXPECT_EQ(0u, resource_provider_->num_resources());
1084 ASSERT_EQ(4u, returned_to_child.size());
1085 EXPECT_EQ(0u, returned_to_child[0].sync_point);
1086 EXPECT_EQ(0u, returned_to_child[1].sync_point);
1087 EXPECT_EQ(0u, returned_to_child[2].sync_point);
1088 EXPECT_EQ(0u, returned_to_child[3].sync_point);
1089 std::set<ResourceProvider::ResourceId> expected_ids;
1090 expected_ids.insert(id1);
1091 expected_ids.insert(id2);
1092 expected_ids.insert(id3);
1093 expected_ids.insert(id4);
1094 std::set<ResourceProvider::ResourceId> returned_ids;
1095 for (unsigned i = 0; i < 4; i++)
1096 returned_ids.insert(returned_to_child[i].id);
1097 EXPECT_EQ(expected_ids, returned_ids);
1098 EXPECT_FALSE(returned_to_child[0].lost);
1099 EXPECT_FALSE(returned_to_child[1].lost);
1100 EXPECT_FALSE(returned_to_child[2].lost);
1101 EXPECT_FALSE(returned_to_child[3].lost);
1104 TEST_P(ResourceProviderTest, TransferGLToSoftware) {
1105 if (GetParam() != ResourceProvider::Bitmap)
1106 return;
1108 scoped_ptr<ResourceProviderContext> child_context_owned(
1109 ResourceProviderContext::Create(shared_data_.get()));
1111 FakeOutputSurfaceClient child_output_surface_client;
1112 scoped_ptr<OutputSurface> child_output_surface(FakeOutputSurface::Create3d(
1113 child_context_owned.PassAs<TestWebGraphicsContext3D>()));
1114 CHECK(child_output_surface->BindToClient(&child_output_surface_client));
1116 scoped_ptr<ResourceProvider> child_resource_provider(ResourceProvider::Create(
1117 child_output_surface.get(), shared_bitmap_manager_.get(), 0, false, 1,
1118 false));
1120 gfx::Size size(1, 1);
1121 ResourceFormat format = RGBA_8888;
1122 size_t pixel_size = TextureSizeBytes(size, format);
1123 ASSERT_EQ(4U, pixel_size);
1125 ResourceProvider::ResourceId id1 = child_resource_provider->CreateResource(
1126 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
1127 uint8_t data1[4] = { 1, 2, 3, 4 };
1128 gfx::Rect rect(size);
1129 child_resource_provider->SetPixels(id1, data1, rect, rect, gfx::Vector2d());
1131 ReturnedResourceArray returned_to_child;
1132 int child_id =
1133 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1135 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1136 resource_ids_to_transfer.push_back(id1);
1137 TransferableResourceArray list;
1138 child_resource_provider->PrepareSendToParent(resource_ids_to_transfer,
1139 &list);
1140 ASSERT_EQ(1u, list.size());
1141 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
1142 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
1143 list[0].mailbox_holder.texture_target);
1144 EXPECT_TRUE(child_resource_provider->InUseByConsumer(id1));
1145 resource_provider_->ReceiveFromChild(child_id, list);
1148 EXPECT_EQ(0u, resource_provider_->num_resources());
1149 ASSERT_EQ(1u, returned_to_child.size());
1150 EXPECT_EQ(returned_to_child[0].id, id1);
1151 ResourceProvider::ResourceIdMap resource_map =
1152 resource_provider_->GetChildToParentMap(child_id);
1153 ResourceProvider::ResourceId mapped_id1 = resource_map[id1];
1154 EXPECT_EQ(0u, mapped_id1);
1156 resource_provider_->DestroyChild(child_id);
1157 EXPECT_EQ(0u, resource_provider_->num_resources());
1159 ASSERT_EQ(1u, returned_to_child.size());
1160 EXPECT_FALSE(returned_to_child[0].lost);
1163 TEST_P(ResourceProviderTest, TransferInvalidSoftware) {
1164 if (GetParam() != ResourceProvider::Bitmap)
1165 return;
1167 gfx::Size size(1, 1);
1168 ResourceFormat format = RGBA_8888;
1169 size_t pixel_size = TextureSizeBytes(size, format);
1170 ASSERT_EQ(4U, pixel_size);
1172 ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource(
1173 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
1174 uint8_t data1[4] = { 1, 2, 3, 4 };
1175 gfx::Rect rect(size);
1176 child_resource_provider_->SetPixels(id1, data1, rect, rect, gfx::Vector2d());
1178 ReturnedResourceArray returned_to_child;
1179 int child_id =
1180 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1182 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1183 resource_ids_to_transfer.push_back(id1);
1184 TransferableResourceArray list;
1185 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1186 &list);
1187 ASSERT_EQ(1u, list.size());
1188 // Make invalid.
1189 list[0].mailbox_holder.mailbox.name[1] = 5;
1190 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1191 resource_provider_->ReceiveFromChild(child_id, list);
1194 EXPECT_EQ(1u, resource_provider_->num_resources());
1195 EXPECT_EQ(0u, returned_to_child.size());
1197 ResourceProvider::ResourceIdMap resource_map =
1198 resource_provider_->GetChildToParentMap(child_id);
1199 ResourceProvider::ResourceId mapped_id1 = resource_map[id1];
1200 EXPECT_NE(0u, mapped_id1);
1202 ResourceProvider::ScopedReadLockSoftware lock(resource_provider_.get(),
1203 mapped_id1);
1204 EXPECT_FALSE(lock.valid());
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, DeleteExportedResources) {
1215 gfx::Size size(1, 1);
1216 ResourceFormat format = RGBA_8888;
1217 size_t pixel_size = TextureSizeBytes(size, format);
1218 ASSERT_EQ(4U, pixel_size);
1220 ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource(
1221 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
1222 uint8_t data1[4] = { 1, 2, 3, 4 };
1223 gfx::Rect rect(size);
1224 child_resource_provider_->SetPixels(id1, data1, rect, rect, gfx::Vector2d());
1226 ResourceProvider::ResourceId id2 = child_resource_provider_->CreateResource(
1227 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
1228 uint8_t data2[4] = {5, 5, 5, 5};
1229 child_resource_provider_->SetPixels(id2, data2, rect, rect, gfx::Vector2d());
1231 ReturnedResourceArray returned_to_child;
1232 int child_id =
1233 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1235 // Transfer some resources to the parent.
1236 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1237 resource_ids_to_transfer.push_back(id1);
1238 resource_ids_to_transfer.push_back(id2);
1239 TransferableResourceArray list;
1240 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1241 &list);
1242 ASSERT_EQ(2u, list.size());
1243 if (GetParam() == ResourceProvider::GLTexture) {
1244 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
1245 EXPECT_NE(0u, list[1].mailbox_holder.sync_point);
1247 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1248 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
1249 resource_provider_->ReceiveFromChild(child_id, list);
1250 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1251 resource_ids_to_transfer);
1254 EXPECT_EQ(2u, resource_provider_->num_resources());
1255 ResourceProvider::ResourceIdMap resource_map =
1256 resource_provider_->GetChildToParentMap(child_id);
1257 ResourceProvider::ResourceId mapped_id1 = resource_map[id1];
1258 ResourceProvider::ResourceId mapped_id2 = resource_map[id2];
1259 EXPECT_NE(0u, mapped_id1);
1260 EXPECT_NE(0u, mapped_id2);
1261 EXPECT_FALSE(resource_provider_->InUseByConsumer(id1));
1262 EXPECT_FALSE(resource_provider_->InUseByConsumer(id2));
1265 // The parent transfers the resources to the grandparent.
1266 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1267 resource_ids_to_transfer.push_back(mapped_id1);
1268 resource_ids_to_transfer.push_back(mapped_id2);
1269 TransferableResourceArray list;
1270 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
1272 ASSERT_EQ(2u, list.size());
1273 if (GetParam() == ResourceProvider::GLTexture) {
1274 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
1275 EXPECT_NE(0u, list[1].mailbox_holder.sync_point);
1277 EXPECT_TRUE(resource_provider_->InUseByConsumer(id1));
1278 EXPECT_TRUE(resource_provider_->InUseByConsumer(id2));
1280 // Release the resource in the parent. Set no resources as being in use. The
1281 // resources are exported so that can't be transferred back yet.
1282 ResourceProvider::ResourceIdArray no_resources;
1283 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
1285 EXPECT_EQ(0u, returned_to_child.size());
1286 EXPECT_EQ(2u, resource_provider_->num_resources());
1288 // Return the resources from the grandparent to the parent. They should be
1289 // returned to the child then.
1290 EXPECT_EQ(2u, list.size());
1291 EXPECT_EQ(mapped_id1, list[0].id);
1292 EXPECT_EQ(mapped_id2, list[1].id);
1293 ReturnedResourceArray returned;
1294 TransferableResource::ReturnResources(list, &returned);
1295 resource_provider_->ReceiveReturnsFromParent(returned);
1297 EXPECT_EQ(0u, resource_provider_->num_resources());
1298 ASSERT_EQ(2u, returned_to_child.size());
1299 if (GetParam() == ResourceProvider::GLTexture) {
1300 EXPECT_NE(0u, returned_to_child[0].sync_point);
1301 EXPECT_NE(0u, returned_to_child[1].sync_point);
1303 EXPECT_FALSE(returned_to_child[0].lost);
1304 EXPECT_FALSE(returned_to_child[1].lost);
1308 TEST_P(ResourceProviderTest, DestroyChildWithExportedResources) {
1309 gfx::Size size(1, 1);
1310 ResourceFormat format = RGBA_8888;
1311 size_t pixel_size = TextureSizeBytes(size, format);
1312 ASSERT_EQ(4U, pixel_size);
1314 ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource(
1315 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
1316 uint8_t data1[4] = {1, 2, 3, 4};
1317 gfx::Rect rect(size);
1318 child_resource_provider_->SetPixels(id1, data1, rect, rect, gfx::Vector2d());
1320 ResourceProvider::ResourceId id2 = child_resource_provider_->CreateResource(
1321 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
1322 uint8_t data2[4] = {5, 5, 5, 5};
1323 child_resource_provider_->SetPixels(id2, data2, rect, rect, gfx::Vector2d());
1325 ReturnedResourceArray returned_to_child;
1326 int child_id =
1327 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1329 // Transfer some resources to the parent.
1330 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1331 resource_ids_to_transfer.push_back(id1);
1332 resource_ids_to_transfer.push_back(id2);
1333 TransferableResourceArray list;
1334 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1335 &list);
1336 ASSERT_EQ(2u, list.size());
1337 if (GetParam() == ResourceProvider::GLTexture) {
1338 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
1339 EXPECT_NE(0u, list[1].mailbox_holder.sync_point);
1341 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1342 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
1343 resource_provider_->ReceiveFromChild(child_id, list);
1344 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1345 resource_ids_to_transfer);
1348 EXPECT_EQ(2u, resource_provider_->num_resources());
1349 ResourceProvider::ResourceIdMap resource_map =
1350 resource_provider_->GetChildToParentMap(child_id);
1351 ResourceProvider::ResourceId mapped_id1 = resource_map[id1];
1352 ResourceProvider::ResourceId mapped_id2 = resource_map[id2];
1353 EXPECT_NE(0u, mapped_id1);
1354 EXPECT_NE(0u, mapped_id2);
1355 EXPECT_FALSE(resource_provider_->InUseByConsumer(id1));
1356 EXPECT_FALSE(resource_provider_->InUseByConsumer(id2));
1359 // The parent transfers the resources to the grandparent.
1360 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1361 resource_ids_to_transfer.push_back(mapped_id1);
1362 resource_ids_to_transfer.push_back(mapped_id2);
1363 TransferableResourceArray list;
1364 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
1366 ASSERT_EQ(2u, list.size());
1367 if (GetParam() == ResourceProvider::GLTexture) {
1368 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
1369 EXPECT_NE(0u, list[1].mailbox_holder.sync_point);
1371 EXPECT_TRUE(resource_provider_->InUseByConsumer(id1));
1372 EXPECT_TRUE(resource_provider_->InUseByConsumer(id2));
1374 // Release the resource in the parent. Set no resources as being in use. The
1375 // resources are exported so that can't be transferred back yet.
1376 ResourceProvider::ResourceIdArray no_resources;
1377 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
1379 // Destroy the child, the resources should not be returned yet.
1380 EXPECT_EQ(0u, returned_to_child.size());
1381 EXPECT_EQ(2u, resource_provider_->num_resources());
1383 resource_provider_->DestroyChild(child_id);
1385 EXPECT_EQ(2u, resource_provider_->num_resources());
1386 ASSERT_EQ(0u, returned_to_child.size());
1388 // Return a resource from the grandparent, it should be returned at this
1389 // point.
1390 EXPECT_EQ(2u, list.size());
1391 EXPECT_EQ(mapped_id1, list[0].id);
1392 EXPECT_EQ(mapped_id2, list[1].id);
1393 TransferableResourceArray return_list;
1394 return_list.push_back(list[1]);
1395 list.pop_back();
1396 ReturnedResourceArray returned;
1397 TransferableResource::ReturnResources(return_list, &returned);
1398 resource_provider_->ReceiveReturnsFromParent(returned);
1400 EXPECT_EQ(1u, resource_provider_->num_resources());
1401 ASSERT_EQ(1u, returned_to_child.size());
1402 if (GetParam() == ResourceProvider::GLTexture) {
1403 EXPECT_NE(0u, returned_to_child[0].sync_point);
1405 EXPECT_FALSE(returned_to_child[0].lost);
1406 returned_to_child.clear();
1408 // Destroy the parent resource provider. The resource that's left should be
1409 // lost at this point, and returned.
1410 resource_provider_.reset();
1411 ASSERT_EQ(1u, returned_to_child.size());
1412 if (GetParam() == ResourceProvider::GLTexture) {
1413 EXPECT_NE(0u, returned_to_child[0].sync_point);
1415 EXPECT_TRUE(returned_to_child[0].lost);
1419 TEST_P(ResourceProviderTest, DeleteTransferredResources) {
1420 gfx::Size size(1, 1);
1421 ResourceFormat format = RGBA_8888;
1422 size_t pixel_size = TextureSizeBytes(size, format);
1423 ASSERT_EQ(4U, pixel_size);
1425 ResourceProvider::ResourceId id = child_resource_provider_->CreateResource(
1426 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
1427 uint8_t data[4] = { 1, 2, 3, 4 };
1428 gfx::Rect rect(size);
1429 child_resource_provider_->SetPixels(id, data, rect, rect, gfx::Vector2d());
1431 ReturnedResourceArray returned_to_child;
1432 int child_id =
1433 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1435 // Transfer some resource to the parent.
1436 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1437 resource_ids_to_transfer.push_back(id);
1438 TransferableResourceArray list;
1439 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1440 &list);
1441 ASSERT_EQ(1u, list.size());
1442 if (GetParam() == ResourceProvider::GLTexture)
1443 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
1444 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id));
1445 resource_provider_->ReceiveFromChild(child_id, list);
1446 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1447 resource_ids_to_transfer);
1450 // Delete textures in the child, while they are transfered.
1451 child_resource_provider_->DeleteResource(id);
1452 EXPECT_EQ(1u, child_resource_provider_->num_resources());
1454 EXPECT_EQ(0u, returned_to_child.size());
1456 // Transfer resources back from the parent to the child. Set no resources as
1457 // being in use.
1458 ResourceProvider::ResourceIdArray no_resources;
1459 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
1461 ASSERT_EQ(1u, returned_to_child.size());
1462 if (GetParam() == ResourceProvider::GLTexture)
1463 EXPECT_NE(0u, returned_to_child[0].sync_point);
1464 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
1466 EXPECT_EQ(0u, child_resource_provider_->num_resources());
1469 TEST_P(ResourceProviderTest, UnuseTransferredResources) {
1470 gfx::Size size(1, 1);
1471 ResourceFormat format = RGBA_8888;
1472 size_t pixel_size = TextureSizeBytes(size, format);
1473 ASSERT_EQ(4U, pixel_size);
1475 ResourceProvider::ResourceId id = child_resource_provider_->CreateResource(
1476 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
1477 uint8_t data[4] = {1, 2, 3, 4};
1478 gfx::Rect rect(size);
1479 child_resource_provider_->SetPixels(id, data, rect, rect, gfx::Vector2d());
1481 ReturnedResourceArray returned_to_child;
1482 int child_id =
1483 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1484 const ResourceProvider::ResourceIdMap& map =
1485 resource_provider_->GetChildToParentMap(child_id);
1487 // Transfer some resource to the parent.
1488 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1489 resource_ids_to_transfer.push_back(id);
1490 TransferableResourceArray list;
1491 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1492 &list);
1493 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id));
1494 resource_provider_->ReceiveFromChild(child_id, list);
1495 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1496 resource_ids_to_transfer);
1498 TransferableResourceArray sent_to_top_level;
1500 // Parent transfers to top-level.
1501 ASSERT_TRUE(map.find(id) != map.end());
1502 ResourceProvider::ResourceId parent_id = map.find(id)->second;
1503 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1504 resource_ids_to_transfer.push_back(parent_id);
1505 resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1506 &sent_to_top_level);
1507 EXPECT_TRUE(resource_provider_->InUseByConsumer(parent_id));
1510 // Stop using resource.
1511 ResourceProvider::ResourceIdArray empty;
1512 resource_provider_->DeclareUsedResourcesFromChild(child_id, empty);
1513 // Resource is not yet returned to the child, since it's in use by the
1514 // top-level.
1515 EXPECT_TRUE(returned_to_child.empty());
1518 // Send the resource to the parent again.
1519 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1520 resource_ids_to_transfer.push_back(id);
1521 TransferableResourceArray list;
1522 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1523 &list);
1524 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id));
1525 resource_provider_->ReceiveFromChild(child_id, list);
1526 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1527 resource_ids_to_transfer);
1530 // Receive returns back from top-level.
1531 ReturnedResourceArray returned;
1532 TransferableResource::ReturnResources(sent_to_top_level, &returned);
1533 resource_provider_->ReceiveReturnsFromParent(returned);
1534 // Resource is still not yet returned to the child, since it's declared used
1535 // in the parent.
1536 EXPECT_TRUE(returned_to_child.empty());
1537 ASSERT_TRUE(map.find(id) != map.end());
1538 ResourceProvider::ResourceId parent_id = map.find(id)->second;
1539 EXPECT_FALSE(resource_provider_->InUseByConsumer(parent_id));
1542 sent_to_top_level.clear();
1543 // Parent transfers again to top-level.
1544 ASSERT_TRUE(map.find(id) != map.end());
1545 ResourceProvider::ResourceId parent_id = map.find(id)->second;
1546 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1547 resource_ids_to_transfer.push_back(parent_id);
1548 resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1549 &sent_to_top_level);
1550 EXPECT_TRUE(resource_provider_->InUseByConsumer(parent_id));
1553 // Receive returns back from top-level.
1554 ReturnedResourceArray returned;
1555 TransferableResource::ReturnResources(sent_to_top_level, &returned);
1556 resource_provider_->ReceiveReturnsFromParent(returned);
1557 // Resource is still not yet returned to the child, since it's still
1558 // declared used in the parent.
1559 EXPECT_TRUE(returned_to_child.empty());
1560 ASSERT_TRUE(map.find(id) != map.end());
1561 ResourceProvider::ResourceId parent_id = map.find(id)->second;
1562 EXPECT_FALSE(resource_provider_->InUseByConsumer(parent_id));
1565 // Stop using resource.
1566 ResourceProvider::ResourceIdArray empty;
1567 resource_provider_->DeclareUsedResourcesFromChild(child_id, empty);
1568 // Resource should have been returned to the child, since it's no longer in
1569 // use by the top-level.
1570 ASSERT_EQ(1u, returned_to_child.size());
1571 EXPECT_EQ(id, returned_to_child[0].id);
1572 EXPECT_EQ(2, returned_to_child[0].count);
1573 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
1574 returned_to_child.clear();
1575 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id));
1579 class ResourceProviderTestTextureFilters : public ResourceProviderTest {
1580 public:
1581 static void RunTest(GLenum child_filter, GLenum parent_filter) {
1582 scoped_ptr<TextureStateTrackingContext> child_context_owned(
1583 new TextureStateTrackingContext);
1584 TextureStateTrackingContext* child_context = child_context_owned.get();
1586 FakeOutputSurfaceClient child_output_surface_client;
1587 scoped_ptr<OutputSurface> child_output_surface(FakeOutputSurface::Create3d(
1588 child_context_owned.PassAs<TestWebGraphicsContext3D>()));
1589 CHECK(child_output_surface->BindToClient(&child_output_surface_client));
1590 scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
1591 new TestSharedBitmapManager());
1593 scoped_ptr<ResourceProvider> child_resource_provider(
1594 ResourceProvider::Create(child_output_surface.get(),
1595 shared_bitmap_manager.get(),
1597 false,
1599 false));
1601 scoped_ptr<TextureStateTrackingContext> parent_context_owned(
1602 new TextureStateTrackingContext);
1603 TextureStateTrackingContext* parent_context = parent_context_owned.get();
1605 FakeOutputSurfaceClient parent_output_surface_client;
1606 scoped_ptr<OutputSurface> parent_output_surface(FakeOutputSurface::Create3d(
1607 parent_context_owned.PassAs<TestWebGraphicsContext3D>()));
1608 CHECK(parent_output_surface->BindToClient(&parent_output_surface_client));
1610 scoped_ptr<ResourceProvider> parent_resource_provider(
1611 ResourceProvider::Create(parent_output_surface.get(),
1612 shared_bitmap_manager.get(),
1614 false,
1616 false));
1618 gfx::Size size(1, 1);
1619 ResourceFormat format = RGBA_8888;
1620 int child_texture_id = 1;
1621 int parent_texture_id = 2;
1623 size_t pixel_size = TextureSizeBytes(size, format);
1624 ASSERT_EQ(4U, pixel_size);
1626 ResourceProvider::ResourceId id = child_resource_provider->CreateResource(
1627 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
1629 // The new texture is created with GL_LINEAR.
1630 EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, child_texture_id))
1631 .Times(2); // Once to create and once to allocate.
1632 EXPECT_CALL(*child_context,
1633 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
1634 EXPECT_CALL(*child_context,
1635 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
1636 EXPECT_CALL(
1637 *child_context,
1638 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
1639 EXPECT_CALL(
1640 *child_context,
1641 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
1642 EXPECT_CALL(*child_context,
1643 texParameteri(GL_TEXTURE_2D,
1644 GL_TEXTURE_POOL_CHROMIUM,
1645 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM));
1646 child_resource_provider->AllocateForTesting(id);
1647 Mock::VerifyAndClearExpectations(child_context);
1649 uint8_t data[4] = { 1, 2, 3, 4 };
1650 gfx::Rect rect(size);
1652 EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, child_texture_id));
1653 child_resource_provider->SetPixels(id, data, rect, rect, gfx::Vector2d());
1654 Mock::VerifyAndClearExpectations(child_context);
1656 // The texture is set to |child_filter| in the child.
1657 EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, child_texture_id));
1658 if (child_filter != GL_LINEAR) {
1659 EXPECT_CALL(
1660 *child_context,
1661 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, child_filter));
1662 EXPECT_CALL(
1663 *child_context,
1664 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, child_filter));
1666 SetResourceFilter(child_resource_provider.get(), id, child_filter);
1667 Mock::VerifyAndClearExpectations(child_context);
1669 ReturnedResourceArray returned_to_child;
1670 int child_id = parent_resource_provider->CreateChild(
1671 GetReturnCallback(&returned_to_child));
1673 // Transfer some resource to the parent.
1674 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1675 resource_ids_to_transfer.push_back(id);
1676 TransferableResourceArray list;
1678 EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, child_texture_id));
1679 EXPECT_CALL(*child_context,
1680 produceTextureCHROMIUM(GL_TEXTURE_2D, _));
1681 EXPECT_CALL(*child_context, insertSyncPoint());
1682 child_resource_provider->PrepareSendToParent(resource_ids_to_transfer,
1683 &list);
1684 Mock::VerifyAndClearExpectations(child_context);
1686 ASSERT_EQ(1u, list.size());
1687 EXPECT_EQ(static_cast<unsigned>(child_filter), list[0].filter);
1689 EXPECT_CALL(*parent_context,
1690 bindTexture(GL_TEXTURE_2D, parent_texture_id));
1691 EXPECT_CALL(*parent_context, consumeTextureCHROMIUM(GL_TEXTURE_2D, _));
1692 parent_resource_provider->ReceiveFromChild(child_id, list);
1694 ResourceProvider::ScopedReadLockGL lock(parent_resource_provider.get(),
1695 list[0].id);
1697 Mock::VerifyAndClearExpectations(parent_context);
1699 parent_resource_provider->DeclareUsedResourcesFromChild(
1700 child_id, resource_ids_to_transfer);
1701 Mock::VerifyAndClearExpectations(parent_context);
1703 ResourceProvider::ResourceIdMap resource_map =
1704 parent_resource_provider->GetChildToParentMap(child_id);
1705 ResourceProvider::ResourceId mapped_id = resource_map[id];
1706 EXPECT_NE(0u, mapped_id);
1708 // The texture is set to |parent_filter| in the parent.
1709 EXPECT_CALL(*parent_context, bindTexture(GL_TEXTURE_2D, parent_texture_id));
1710 EXPECT_CALL(
1711 *parent_context,
1712 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, parent_filter));
1713 EXPECT_CALL(
1714 *parent_context,
1715 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, parent_filter));
1716 SetResourceFilter(parent_resource_provider.get(), mapped_id, parent_filter);
1717 Mock::VerifyAndClearExpectations(parent_context);
1719 // The texture should be reset to |child_filter| in the parent when it is
1720 // returned, since that is how it was received.
1721 EXPECT_CALL(*parent_context, bindTexture(GL_TEXTURE_2D, parent_texture_id));
1722 EXPECT_CALL(
1723 *parent_context,
1724 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, child_filter));
1725 EXPECT_CALL(
1726 *parent_context,
1727 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, child_filter));
1730 EXPECT_EQ(0u, returned_to_child.size());
1732 // Transfer resources back from the parent to the child. Set no resources
1733 // as being in use.
1734 ResourceProvider::ResourceIdArray no_resources;
1735 EXPECT_CALL(*parent_context, insertSyncPoint());
1736 parent_resource_provider->DeclareUsedResourcesFromChild(child_id,
1737 no_resources);
1738 Mock::VerifyAndClearExpectations(parent_context);
1740 ASSERT_EQ(1u, returned_to_child.size());
1741 child_resource_provider->ReceiveReturnsFromParent(returned_to_child);
1744 // The child remembers the texture filter is set to |child_filter|.
1745 EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, child_texture_id));
1746 SetResourceFilter(child_resource_provider.get(), id, child_filter);
1747 Mock::VerifyAndClearExpectations(child_context);
1751 TEST_P(ResourceProviderTest, TextureFilters_ChildNearestParentLinear) {
1752 if (GetParam() != ResourceProvider::GLTexture)
1753 return;
1754 ResourceProviderTestTextureFilters::RunTest(GL_NEAREST, GL_LINEAR);
1757 TEST_P(ResourceProviderTest, TextureFilters_ChildLinearParentNearest) {
1758 if (GetParam() != ResourceProvider::GLTexture)
1759 return;
1760 ResourceProviderTestTextureFilters::RunTest(GL_LINEAR, GL_NEAREST);
1763 TEST_P(ResourceProviderTest, TransferMailboxResources) {
1764 // Other mailbox transfers tested elsewhere.
1765 if (GetParam() != ResourceProvider::GLTexture)
1766 return;
1767 unsigned texture = context()->createTexture();
1768 context()->bindTexture(GL_TEXTURE_2D, texture);
1769 uint8_t data[4] = { 1, 2, 3, 4 };
1770 context()->texImage2D(
1771 GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &data);
1772 gpu::Mailbox mailbox;
1773 context()->genMailboxCHROMIUM(mailbox.name);
1774 context()->produceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
1775 uint32 sync_point = context()->insertSyncPoint();
1777 // All the logic below assumes that the sync points are all positive.
1778 EXPECT_LT(0u, sync_point);
1780 uint32 release_sync_point = 0;
1781 bool lost_resource = false;
1782 ReleaseCallback callback =
1783 base::Bind(ReleaseTextureMailbox, &release_sync_point, &lost_resource);
1784 ResourceProvider::ResourceId resource =
1785 resource_provider_->CreateResourceFromTextureMailbox(
1786 TextureMailbox(mailbox, GL_TEXTURE_2D, sync_point),
1787 SingleReleaseCallback::Create(callback));
1788 EXPECT_EQ(1u, context()->NumTextures());
1789 EXPECT_EQ(0u, release_sync_point);
1791 // Transfer the resource, expect the sync points to be consistent.
1792 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1793 resource_ids_to_transfer.push_back(resource);
1794 TransferableResourceArray list;
1795 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
1796 ASSERT_EQ(1u, list.size());
1797 EXPECT_LE(sync_point, list[0].mailbox_holder.sync_point);
1798 EXPECT_EQ(0,
1799 memcmp(mailbox.name,
1800 list[0].mailbox_holder.mailbox.name,
1801 sizeof(mailbox.name)));
1802 EXPECT_EQ(0u, release_sync_point);
1804 context()->waitSyncPoint(list[0].mailbox_holder.sync_point);
1805 unsigned other_texture = context()->createTexture();
1806 context()->bindTexture(GL_TEXTURE_2D, other_texture);
1807 context()->consumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
1808 uint8_t test_data[4] = { 0 };
1809 context()->GetPixels(
1810 gfx::Size(1, 1), RGBA_8888, test_data);
1811 EXPECT_EQ(0, memcmp(data, test_data, sizeof(data)));
1812 context()->produceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
1813 context()->deleteTexture(other_texture);
1814 list[0].mailbox_holder.sync_point = context()->insertSyncPoint();
1815 EXPECT_LT(0u, list[0].mailbox_holder.sync_point);
1817 // Receive the resource, then delete it, expect the sync points to be
1818 // consistent.
1819 ReturnedResourceArray returned;
1820 TransferableResource::ReturnResources(list, &returned);
1821 resource_provider_->ReceiveReturnsFromParent(returned);
1822 EXPECT_EQ(1u, context()->NumTextures());
1823 EXPECT_EQ(0u, release_sync_point);
1825 resource_provider_->DeleteResource(resource);
1826 EXPECT_LE(list[0].mailbox_holder.sync_point, release_sync_point);
1827 EXPECT_FALSE(lost_resource);
1830 // We're going to do the same thing as above, but testing the case where we
1831 // delete the resource before we receive it back.
1832 sync_point = release_sync_point;
1833 EXPECT_LT(0u, sync_point);
1834 release_sync_point = 0;
1835 resource = resource_provider_->CreateResourceFromTextureMailbox(
1836 TextureMailbox(mailbox, GL_TEXTURE_2D, sync_point),
1837 SingleReleaseCallback::Create(callback));
1838 EXPECT_EQ(1u, context()->NumTextures());
1839 EXPECT_EQ(0u, release_sync_point);
1841 // Transfer the resource, expect the sync points to be consistent.
1842 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1843 resource_ids_to_transfer.push_back(resource);
1844 TransferableResourceArray list;
1845 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
1846 ASSERT_EQ(1u, list.size());
1847 EXPECT_LE(sync_point, list[0].mailbox_holder.sync_point);
1848 EXPECT_EQ(0,
1849 memcmp(mailbox.name,
1850 list[0].mailbox_holder.mailbox.name,
1851 sizeof(mailbox.name)));
1852 EXPECT_EQ(0u, release_sync_point);
1854 context()->waitSyncPoint(list[0].mailbox_holder.sync_point);
1855 unsigned other_texture = context()->createTexture();
1856 context()->bindTexture(GL_TEXTURE_2D, other_texture);
1857 context()->consumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
1858 uint8_t test_data[4] = { 0 };
1859 context()->GetPixels(
1860 gfx::Size(1, 1), RGBA_8888, test_data);
1861 EXPECT_EQ(0, memcmp(data, test_data, sizeof(data)));
1862 context()->produceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
1863 context()->deleteTexture(other_texture);
1864 list[0].mailbox_holder.sync_point = context()->insertSyncPoint();
1865 EXPECT_LT(0u, list[0].mailbox_holder.sync_point);
1867 // Delete the resource, which shouldn't do anything.
1868 resource_provider_->DeleteResource(resource);
1869 EXPECT_EQ(1u, context()->NumTextures());
1870 EXPECT_EQ(0u, release_sync_point);
1872 // Then receive the resource which should release the mailbox, expect the
1873 // sync points to be consistent.
1874 ReturnedResourceArray returned;
1875 TransferableResource::ReturnResources(list, &returned);
1876 resource_provider_->ReceiveReturnsFromParent(returned);
1877 EXPECT_LE(list[0].mailbox_holder.sync_point, release_sync_point);
1878 EXPECT_FALSE(lost_resource);
1881 context()->waitSyncPoint(release_sync_point);
1882 context()->bindTexture(GL_TEXTURE_2D, texture);
1883 context()->consumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
1884 context()->deleteTexture(texture);
1887 TEST_P(ResourceProviderTest, LostResourceInParent) {
1888 gfx::Size size(1, 1);
1889 ResourceFormat format = RGBA_8888;
1890 ResourceProvider::ResourceId resource =
1891 child_resource_provider_->CreateResource(
1892 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
1893 child_resource_provider_->AllocateForTesting(resource);
1894 // Expect a GL resource to be lost.
1895 bool should_lose_resource = GetParam() == ResourceProvider::GLTexture;
1897 ReturnedResourceArray returned_to_child;
1898 int child_id =
1899 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1901 // Transfer the resource to the parent.
1902 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1903 resource_ids_to_transfer.push_back(resource);
1904 TransferableResourceArray list;
1905 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1906 &list);
1907 EXPECT_EQ(1u, list.size());
1909 resource_provider_->ReceiveFromChild(child_id, list);
1910 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1911 resource_ids_to_transfer);
1914 // Lose the output surface in the parent.
1915 resource_provider_->DidLoseOutputSurface();
1918 EXPECT_EQ(0u, returned_to_child.size());
1920 // Transfer resources back from the parent to the child. Set no resources as
1921 // being in use.
1922 ResourceProvider::ResourceIdArray no_resources;
1923 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
1925 // Expect a GL resource to be lost.
1926 ASSERT_EQ(1u, returned_to_child.size());
1927 EXPECT_EQ(should_lose_resource, returned_to_child[0].lost);
1928 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
1929 returned_to_child.clear();
1932 // A GL resource should be lost.
1933 EXPECT_EQ(should_lose_resource, child_resource_provider_->IsLost(resource));
1935 // Lost resources stay in use in the parent forever.
1936 EXPECT_EQ(should_lose_resource,
1937 child_resource_provider_->InUseByConsumer(resource));
1940 TEST_P(ResourceProviderTest, LostResourceInGrandParent) {
1941 gfx::Size size(1, 1);
1942 ResourceFormat format = RGBA_8888;
1943 ResourceProvider::ResourceId resource =
1944 child_resource_provider_->CreateResource(
1945 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
1946 child_resource_provider_->AllocateForTesting(resource);
1948 ReturnedResourceArray returned_to_child;
1949 int child_id =
1950 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1952 // Transfer the resource to the parent.
1953 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1954 resource_ids_to_transfer.push_back(resource);
1955 TransferableResourceArray list;
1956 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1957 &list);
1958 EXPECT_EQ(1u, list.size());
1960 resource_provider_->ReceiveFromChild(child_id, list);
1961 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1962 resource_ids_to_transfer);
1966 ResourceProvider::ResourceIdMap resource_map =
1967 resource_provider_->GetChildToParentMap(child_id);
1968 ResourceProvider::ResourceId parent_resource = resource_map[resource];
1969 EXPECT_NE(0u, parent_resource);
1971 // Transfer to a grandparent.
1972 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1973 resource_ids_to_transfer.push_back(parent_resource);
1974 TransferableResourceArray list;
1975 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
1977 // Receive back a lost resource from the grandparent.
1978 EXPECT_EQ(1u, list.size());
1979 EXPECT_EQ(parent_resource, list[0].id);
1980 ReturnedResourceArray returned;
1981 TransferableResource::ReturnResources(list, &returned);
1982 EXPECT_EQ(1u, returned.size());
1983 EXPECT_EQ(parent_resource, returned[0].id);
1984 returned[0].lost = true;
1985 resource_provider_->ReceiveReturnsFromParent(returned);
1987 // The resource should be lost.
1988 EXPECT_TRUE(resource_provider_->IsLost(parent_resource));
1990 // Lost resources stay in use in the parent forever.
1991 EXPECT_TRUE(resource_provider_->InUseByConsumer(parent_resource));
1995 EXPECT_EQ(0u, returned_to_child.size());
1997 // Transfer resources back from the parent to the child. Set no resources as
1998 // being in use.
1999 ResourceProvider::ResourceIdArray no_resources;
2000 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
2002 // Expect the resource to be lost.
2003 ASSERT_EQ(1u, returned_to_child.size());
2004 EXPECT_TRUE(returned_to_child[0].lost);
2005 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
2006 returned_to_child.clear();
2009 // The resource should be lost.
2010 EXPECT_TRUE(child_resource_provider_->IsLost(resource));
2012 // Lost resources stay in use in the parent forever.
2013 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(resource));
2016 TEST_P(ResourceProviderTest, LostMailboxInParent) {
2017 uint32 release_sync_point = 0;
2018 bool lost_resource = false;
2019 bool release_called = false;
2020 uint32 sync_point = 0;
2021 ResourceProvider::ResourceId resource = CreateChildMailbox(
2022 &release_sync_point, &lost_resource, &release_called, &sync_point);
2024 ReturnedResourceArray returned_to_child;
2025 int child_id =
2026 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
2028 // Transfer the resource to the parent.
2029 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2030 resource_ids_to_transfer.push_back(resource);
2031 TransferableResourceArray list;
2032 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
2033 &list);
2034 EXPECT_EQ(1u, list.size());
2036 resource_provider_->ReceiveFromChild(child_id, list);
2037 resource_provider_->DeclareUsedResourcesFromChild(child_id,
2038 resource_ids_to_transfer);
2041 // Lose the output surface in the parent.
2042 resource_provider_->DidLoseOutputSurface();
2045 EXPECT_EQ(0u, returned_to_child.size());
2047 // Transfer resources back from the parent to the child. Set no resources as
2048 // being in use.
2049 ResourceProvider::ResourceIdArray no_resources;
2050 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
2052 ASSERT_EQ(1u, returned_to_child.size());
2053 // Losing an output surface only loses hardware resources.
2054 EXPECT_EQ(returned_to_child[0].lost,
2055 GetParam() == ResourceProvider::GLTexture);
2056 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
2057 returned_to_child.clear();
2060 // Delete the resource in the child. Expect the resource to be lost if it's
2061 // a GL texture.
2062 child_resource_provider_->DeleteResource(resource);
2063 EXPECT_EQ(lost_resource, GetParam() == ResourceProvider::GLTexture);
2066 TEST_P(ResourceProviderTest, LostMailboxInGrandParent) {
2067 uint32 release_sync_point = 0;
2068 bool lost_resource = false;
2069 bool release_called = false;
2070 uint32 sync_point = 0;
2071 ResourceProvider::ResourceId resource = CreateChildMailbox(
2072 &release_sync_point, &lost_resource, &release_called, &sync_point);
2074 ReturnedResourceArray returned_to_child;
2075 int child_id =
2076 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
2078 // Transfer the resource to the parent.
2079 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2080 resource_ids_to_transfer.push_back(resource);
2081 TransferableResourceArray list;
2082 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
2083 &list);
2084 EXPECT_EQ(1u, list.size());
2086 resource_provider_->ReceiveFromChild(child_id, list);
2087 resource_provider_->DeclareUsedResourcesFromChild(child_id,
2088 resource_ids_to_transfer);
2092 ResourceProvider::ResourceIdMap resource_map =
2093 resource_provider_->GetChildToParentMap(child_id);
2094 ResourceProvider::ResourceId parent_resource = resource_map[resource];
2095 EXPECT_NE(0u, parent_resource);
2097 // Transfer to a grandparent.
2098 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2099 resource_ids_to_transfer.push_back(parent_resource);
2100 TransferableResourceArray list;
2101 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
2103 // Receive back a lost resource from the grandparent.
2104 EXPECT_EQ(1u, list.size());
2105 EXPECT_EQ(parent_resource, list[0].id);
2106 ReturnedResourceArray returned;
2107 TransferableResource::ReturnResources(list, &returned);
2108 EXPECT_EQ(1u, returned.size());
2109 EXPECT_EQ(parent_resource, returned[0].id);
2110 returned[0].lost = true;
2111 resource_provider_->ReceiveReturnsFromParent(returned);
2115 EXPECT_EQ(0u, returned_to_child.size());
2117 // Transfer resources back from the parent to the child. Set no resources as
2118 // being in use.
2119 ResourceProvider::ResourceIdArray no_resources;
2120 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
2122 // Expect the resource to be lost.
2123 ASSERT_EQ(1u, returned_to_child.size());
2124 EXPECT_TRUE(returned_to_child[0].lost);
2125 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
2126 returned_to_child.clear();
2129 // Delete the resource in the child. Expect the resource to be lost.
2130 child_resource_provider_->DeleteResource(resource);
2131 EXPECT_TRUE(lost_resource);
2134 TEST_P(ResourceProviderTest, Shutdown) {
2135 uint32 release_sync_point = 0;
2136 bool lost_resource = false;
2137 bool release_called = false;
2138 uint32 sync_point = 0;
2139 CreateChildMailbox(
2140 &release_sync_point, &lost_resource, &release_called, &sync_point);
2142 EXPECT_EQ(0u, release_sync_point);
2143 EXPECT_FALSE(lost_resource);
2145 child_resource_provider_.reset();
2147 if (GetParam() == ResourceProvider::GLTexture) {
2148 EXPECT_LE(sync_point, release_sync_point);
2150 EXPECT_TRUE(release_called);
2151 EXPECT_FALSE(lost_resource);
2154 TEST_P(ResourceProviderTest, ShutdownWithExportedResource) {
2155 uint32 release_sync_point = 0;
2156 bool lost_resource = false;
2157 bool release_called = false;
2158 uint32 sync_point = 0;
2159 ResourceProvider::ResourceId resource = CreateChildMailbox(
2160 &release_sync_point, &lost_resource, &release_called, &sync_point);
2162 // Transfer the resource, so we can't release it properly on shutdown.
2163 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2164 resource_ids_to_transfer.push_back(resource);
2165 TransferableResourceArray list;
2166 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
2167 &list);
2169 EXPECT_EQ(0u, release_sync_point);
2170 EXPECT_FALSE(lost_resource);
2172 child_resource_provider_.reset();
2174 // Since the resource is in the parent, the child considers it lost.
2175 EXPECT_EQ(0u, release_sync_point);
2176 EXPECT_TRUE(lost_resource);
2179 TEST_P(ResourceProviderTest, LostContext) {
2180 // TextureMailbox callbacks only exist for GL textures for now.
2181 if (GetParam() != ResourceProvider::GLTexture)
2182 return;
2183 unsigned texture = context()->createTexture();
2184 context()->bindTexture(GL_TEXTURE_2D, texture);
2185 gpu::Mailbox mailbox;
2186 context()->genMailboxCHROMIUM(mailbox.name);
2187 context()->produceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
2188 uint32 sync_point = context()->insertSyncPoint();
2190 EXPECT_LT(0u, sync_point);
2192 uint32 release_sync_point = 0;
2193 bool lost_resource = false;
2194 scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create(
2195 base::Bind(ReleaseTextureMailbox, &release_sync_point, &lost_resource));
2196 resource_provider_->CreateResourceFromTextureMailbox(
2197 TextureMailbox(mailbox, GL_TEXTURE_2D, sync_point), callback.Pass());
2199 EXPECT_EQ(0u, release_sync_point);
2200 EXPECT_FALSE(lost_resource);
2202 resource_provider_->DidLoseOutputSurface();
2203 resource_provider_.reset();
2205 EXPECT_LE(sync_point, release_sync_point);
2206 EXPECT_TRUE(lost_resource);
2209 TEST_P(ResourceProviderTest, ScopedSampler) {
2210 // Sampling is only supported for GL textures.
2211 if (GetParam() != ResourceProvider::GLTexture)
2212 return;
2214 scoped_ptr<TextureStateTrackingContext> context_owned(
2215 new TextureStateTrackingContext);
2216 TextureStateTrackingContext* context = context_owned.get();
2218 FakeOutputSurfaceClient output_surface_client;
2219 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
2220 context_owned.PassAs<TestWebGraphicsContext3D>()));
2221 CHECK(output_surface->BindToClient(&output_surface_client));
2223 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
2224 output_surface.get(), shared_bitmap_manager_.get(), 0, false, 1, false));
2226 gfx::Size size(1, 1);
2227 ResourceFormat format = RGBA_8888;
2228 int texture_id = 1;
2230 ResourceProvider::ResourceId id = resource_provider->CreateResource(
2231 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
2233 // Check that the texture gets created with the right sampler settings.
2234 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id))
2235 .Times(2); // Once to create and once to allocate.
2236 EXPECT_CALL(*context,
2237 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
2238 EXPECT_CALL(*context,
2239 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
2240 EXPECT_CALL(
2241 *context,
2242 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
2243 EXPECT_CALL(
2244 *context,
2245 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
2246 EXPECT_CALL(*context,
2247 texParameteri(GL_TEXTURE_2D,
2248 GL_TEXTURE_POOL_CHROMIUM,
2249 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM));
2251 resource_provider->AllocateForTesting(id);
2252 Mock::VerifyAndClearExpectations(context);
2254 // Creating a sampler with the default filter should not change any texture
2255 // parameters.
2257 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
2258 ResourceProvider::ScopedSamplerGL sampler(
2259 resource_provider.get(), id, GL_TEXTURE_2D, GL_LINEAR);
2260 Mock::VerifyAndClearExpectations(context);
2263 // Using a different filter should be reflected in the texture parameters.
2265 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
2266 EXPECT_CALL(
2267 *context,
2268 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
2269 EXPECT_CALL(
2270 *context,
2271 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
2272 ResourceProvider::ScopedSamplerGL sampler(
2273 resource_provider.get(), id, GL_TEXTURE_2D, GL_NEAREST);
2274 Mock::VerifyAndClearExpectations(context);
2277 // Test resetting to the default filter.
2279 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
2280 EXPECT_CALL(*context,
2281 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
2282 EXPECT_CALL(*context,
2283 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
2284 ResourceProvider::ScopedSamplerGL sampler(
2285 resource_provider.get(), id, GL_TEXTURE_2D, GL_LINEAR);
2286 Mock::VerifyAndClearExpectations(context);
2290 TEST_P(ResourceProviderTest, ManagedResource) {
2291 // Sampling is only supported for GL textures.
2292 if (GetParam() != ResourceProvider::GLTexture)
2293 return;
2295 scoped_ptr<TextureStateTrackingContext> context_owned(
2296 new TextureStateTrackingContext);
2297 TextureStateTrackingContext* context = context_owned.get();
2299 FakeOutputSurfaceClient output_surface_client;
2300 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
2301 context_owned.PassAs<TestWebGraphicsContext3D>()));
2302 CHECK(output_surface->BindToClient(&output_surface_client));
2304 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
2305 output_surface.get(), shared_bitmap_manager_.get(), 0, false, 1, false));
2307 gfx::Size size(1, 1);
2308 ResourceFormat format = RGBA_8888;
2309 int texture_id = 1;
2311 // Check that the texture gets created with the right sampler settings.
2312 ResourceProvider::ResourceId id = resource_provider->CreateManagedResource(
2313 size,
2314 GL_TEXTURE_2D,
2315 GL_CLAMP_TO_EDGE,
2316 ResourceProvider::TextureUsageAny,
2317 format);
2318 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
2319 EXPECT_CALL(*context,
2320 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
2321 EXPECT_CALL(*context,
2322 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
2323 EXPECT_CALL(
2324 *context,
2325 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
2326 EXPECT_CALL(
2327 *context,
2328 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
2329 EXPECT_CALL(*context,
2330 texParameteri(GL_TEXTURE_2D,
2331 GL_TEXTURE_POOL_CHROMIUM,
2332 GL_TEXTURE_POOL_MANAGED_CHROMIUM));
2333 resource_provider->CreateForTesting(id);
2334 EXPECT_NE(0u, id);
2336 Mock::VerifyAndClearExpectations(context);
2339 TEST_P(ResourceProviderTest, TextureWrapMode) {
2340 // Sampling is only supported for GL textures.
2341 if (GetParam() != ResourceProvider::GLTexture)
2342 return;
2344 scoped_ptr<TextureStateTrackingContext> context_owned(
2345 new TextureStateTrackingContext);
2346 TextureStateTrackingContext* context = context_owned.get();
2348 FakeOutputSurfaceClient output_surface_client;
2349 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
2350 context_owned.PassAs<TestWebGraphicsContext3D>()));
2351 CHECK(output_surface->BindToClient(&output_surface_client));
2353 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
2354 output_surface.get(), shared_bitmap_manager_.get(), 0, false, 1, false));
2356 gfx::Size size(1, 1);
2357 ResourceFormat format = RGBA_8888;
2358 GLenum texture_pool = GL_TEXTURE_POOL_UNMANAGED_CHROMIUM;
2360 for (int texture_id = 1; texture_id <= 2; ++texture_id) {
2361 GLint wrap_mode = texture_id == 1 ? GL_CLAMP_TO_EDGE : GL_REPEAT;
2362 // Check that the texture gets created with the right sampler settings.
2363 ResourceProvider::ResourceId id =
2364 resource_provider->CreateGLTexture(size,
2365 GL_TEXTURE_2D,
2366 texture_pool,
2367 wrap_mode,
2368 ResourceProvider::TextureUsageAny,
2369 format);
2370 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
2371 EXPECT_CALL(*context,
2372 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
2373 EXPECT_CALL(*context,
2374 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
2375 EXPECT_CALL(
2376 *context,
2377 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap_mode));
2378 EXPECT_CALL(
2379 *context,
2380 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap_mode));
2381 EXPECT_CALL(*context,
2382 texParameteri(GL_TEXTURE_2D,
2383 GL_TEXTURE_POOL_CHROMIUM,
2384 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM));
2385 resource_provider->CreateForTesting(id);
2386 EXPECT_NE(0u, id);
2388 Mock::VerifyAndClearExpectations(context);
2392 TEST_P(ResourceProviderTest, TextureMailbox_SharedMemory) {
2393 if (GetParam() != ResourceProvider::Bitmap)
2394 return;
2396 gfx::Size size(64, 64);
2397 const uint32_t kBadBeef = 0xbadbeef;
2398 scoped_ptr<base::SharedMemory> shared_memory(
2399 CreateAndFillSharedMemory(size, kBadBeef));
2401 FakeOutputSurfaceClient output_surface_client;
2402 scoped_ptr<OutputSurface> output_surface(
2403 FakeOutputSurface::CreateSoftware(make_scoped_ptr(
2404 new SoftwareOutputDevice)));
2405 CHECK(output_surface->BindToClient(&output_surface_client));
2407 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
2408 output_surface.get(), shared_bitmap_manager_.get(), 0, false, 1, false));
2410 scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create(
2411 base::Bind(&EmptyReleaseCallback));
2412 TextureMailbox mailbox(shared_memory.get(), size);
2414 ResourceProvider::ResourceId id =
2415 resource_provider->CreateResourceFromTextureMailbox(
2416 mailbox, callback.Pass());
2417 EXPECT_NE(0u, id);
2420 ResourceProvider::ScopedReadLockSoftware lock(resource_provider.get(), id);
2421 const SkBitmap* sk_bitmap = lock.sk_bitmap();
2422 EXPECT_EQ(sk_bitmap->width(), size.width());
2423 EXPECT_EQ(sk_bitmap->height(), size.height());
2424 EXPECT_EQ(*sk_bitmap->getAddr32(16, 16), kBadBeef);
2428 TEST_P(ResourceProviderTest, TextureMailbox_GLTexture2D) {
2429 // Mailboxing is only supported for GL textures.
2430 if (GetParam() != ResourceProvider::GLTexture)
2431 return;
2433 scoped_ptr<TextureStateTrackingContext> context_owned(
2434 new TextureStateTrackingContext);
2435 TextureStateTrackingContext* context = context_owned.get();
2437 FakeOutputSurfaceClient output_surface_client;
2438 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
2439 context_owned.PassAs<TestWebGraphicsContext3D>()));
2440 CHECK(output_surface->BindToClient(&output_surface_client));
2442 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
2443 output_surface.get(), shared_bitmap_manager_.get(), 0, false, 1, false));
2445 unsigned texture_id = 1;
2446 uint32 sync_point = 30;
2447 unsigned target = GL_TEXTURE_2D;
2449 EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
2450 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
2451 EXPECT_CALL(*context, insertSyncPoint()).Times(0);
2452 EXPECT_CALL(*context, produceTextureCHROMIUM(_, _)).Times(0);
2453 EXPECT_CALL(*context, consumeTextureCHROMIUM(_, _)).Times(0);
2455 gpu::Mailbox gpu_mailbox;
2456 memcpy(gpu_mailbox.name, "Hello world", strlen("Hello world") + 1);
2457 scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create(
2458 base::Bind(&EmptyReleaseCallback));
2460 TextureMailbox mailbox(gpu_mailbox, target, sync_point);
2462 ResourceProvider::ResourceId id =
2463 resource_provider->CreateResourceFromTextureMailbox(
2464 mailbox, callback.Pass());
2465 EXPECT_NE(0u, id);
2467 Mock::VerifyAndClearExpectations(context);
2470 // Using the texture does a consume of the mailbox.
2471 EXPECT_CALL(*context, bindTexture(target, texture_id));
2472 EXPECT_CALL(*context, waitSyncPoint(sync_point));
2473 EXPECT_CALL(*context, consumeTextureCHROMIUM(target, _));
2475 EXPECT_CALL(*context, insertSyncPoint()).Times(0);
2476 EXPECT_CALL(*context, produceTextureCHROMIUM(_, _)).Times(0);
2478 ResourceProvider::ScopedReadLockGL lock(resource_provider.get(), id);
2479 Mock::VerifyAndClearExpectations(context);
2481 // When done with it, a sync point should be inserted, but no produce is
2482 // necessary.
2483 EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
2484 EXPECT_CALL(*context, insertSyncPoint());
2485 EXPECT_CALL(*context, produceTextureCHROMIUM(_, _)).Times(0);
2487 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
2488 EXPECT_CALL(*context, consumeTextureCHROMIUM(_, _)).Times(0);
2492 TEST_P(ResourceProviderTest, TextureMailbox_GLTextureExternalOES) {
2493 // Mailboxing is only supported for GL textures.
2494 if (GetParam() != ResourceProvider::GLTexture)
2495 return;
2497 scoped_ptr<TextureStateTrackingContext> context_owned(
2498 new TextureStateTrackingContext);
2499 TextureStateTrackingContext* context = context_owned.get();
2501 FakeOutputSurfaceClient output_surface_client;
2502 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
2503 context_owned.PassAs<TestWebGraphicsContext3D>()));
2504 CHECK(output_surface->BindToClient(&output_surface_client));
2506 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
2507 output_surface.get(), shared_bitmap_manager_.get(), 0, false, 1, false));
2509 unsigned texture_id = 1;
2510 uint32 sync_point = 30;
2511 unsigned target = GL_TEXTURE_EXTERNAL_OES;
2513 EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
2514 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
2515 EXPECT_CALL(*context, insertSyncPoint()).Times(0);
2516 EXPECT_CALL(*context, produceTextureCHROMIUM(_, _)).Times(0);
2517 EXPECT_CALL(*context, consumeTextureCHROMIUM(_, _)).Times(0);
2519 gpu::Mailbox gpu_mailbox;
2520 memcpy(gpu_mailbox.name, "Hello world", strlen("Hello world") + 1);
2521 scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create(
2522 base::Bind(&EmptyReleaseCallback));
2524 TextureMailbox mailbox(gpu_mailbox, target, sync_point);
2526 ResourceProvider::ResourceId id =
2527 resource_provider->CreateResourceFromTextureMailbox(
2528 mailbox, callback.Pass());
2529 EXPECT_NE(0u, id);
2531 Mock::VerifyAndClearExpectations(context);
2534 // Using the texture does a consume of the mailbox.
2535 EXPECT_CALL(*context, bindTexture(target, texture_id));
2536 EXPECT_CALL(*context, waitSyncPoint(sync_point));
2537 EXPECT_CALL(*context, consumeTextureCHROMIUM(target, _));
2539 EXPECT_CALL(*context, insertSyncPoint()).Times(0);
2540 EXPECT_CALL(*context, produceTextureCHROMIUM(_, _)).Times(0);
2542 ResourceProvider::ScopedReadLockGL lock(resource_provider.get(), id);
2543 Mock::VerifyAndClearExpectations(context);
2545 // When done with it, a sync point should be inserted, but no produce is
2546 // necessary.
2547 EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
2548 EXPECT_CALL(*context, insertSyncPoint());
2549 EXPECT_CALL(*context, produceTextureCHROMIUM(_, _)).Times(0);
2551 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
2552 EXPECT_CALL(*context, consumeTextureCHROMIUM(_, _)).Times(0);
2556 class AllocationTrackingContext3D : public TestWebGraphicsContext3D {
2557 public:
2558 MOCK_METHOD0(NextTextureId, GLuint());
2559 MOCK_METHOD1(RetireTextureId, void(GLuint id));
2560 MOCK_METHOD2(bindTexture, void(GLenum target, GLuint texture));
2561 MOCK_METHOD5(texStorage2DEXT,
2562 void(GLenum target,
2563 GLint levels,
2564 GLuint internalformat,
2565 GLint width,
2566 GLint height));
2567 MOCK_METHOD9(texImage2D,
2568 void(GLenum target,
2569 GLint level,
2570 GLenum internalformat,
2571 GLsizei width,
2572 GLsizei height,
2573 GLint border,
2574 GLenum format,
2575 GLenum type,
2576 const void* pixels));
2577 MOCK_METHOD9(texSubImage2D,
2578 void(GLenum target,
2579 GLint level,
2580 GLint xoffset,
2581 GLint yoffset,
2582 GLsizei width,
2583 GLsizei height,
2584 GLenum format,
2585 GLenum type,
2586 const void* pixels));
2587 MOCK_METHOD9(asyncTexImage2DCHROMIUM,
2588 void(GLenum target,
2589 GLint level,
2590 GLenum internalformat,
2591 GLsizei width,
2592 GLsizei height,
2593 GLint border,
2594 GLenum format,
2595 GLenum type,
2596 const void* pixels));
2597 MOCK_METHOD9(asyncTexSubImage2DCHROMIUM,
2598 void(GLenum target,
2599 GLint level,
2600 GLint xoffset,
2601 GLint yoffset,
2602 GLsizei width,
2603 GLsizei height,
2604 GLenum format,
2605 GLenum type,
2606 const void* pixels));
2607 MOCK_METHOD8(compressedTexImage2D,
2608 void(GLenum target,
2609 GLint level,
2610 GLenum internalformat,
2611 GLsizei width,
2612 GLsizei height,
2613 GLint border,
2614 GLsizei image_size,
2615 const void* data));
2616 MOCK_METHOD1(waitAsyncTexImage2DCHROMIUM, void(GLenum));
2617 MOCK_METHOD4(createImageCHROMIUM, GLuint(GLsizei, GLsizei, GLenum, GLenum));
2618 MOCK_METHOD1(destroyImageCHROMIUM, void(GLuint));
2619 MOCK_METHOD1(mapImageCHROMIUM, void*(GLuint));
2620 MOCK_METHOD3(getImageParameterivCHROMIUM, void(GLuint, GLenum, GLint*));
2621 MOCK_METHOD1(unmapImageCHROMIUM, void(GLuint));
2622 MOCK_METHOD2(bindTexImage2DCHROMIUM, void(GLenum, GLint));
2623 MOCK_METHOD2(releaseTexImage2DCHROMIUM, void(GLenum, GLint));
2625 // We're mocking bindTexture, so we override
2626 // TestWebGraphicsContext3D::texParameteri to avoid assertions related to the
2627 // currently bound texture.
2628 virtual void texParameteri(GLenum target, GLenum pname, GLint param) {}
2631 TEST_P(ResourceProviderTest, TextureAllocation) {
2632 // Only for GL textures.
2633 if (GetParam() != ResourceProvider::GLTexture)
2634 return;
2635 scoped_ptr<AllocationTrackingContext3D> context_owned(
2636 new StrictMock<AllocationTrackingContext3D>);
2637 AllocationTrackingContext3D* context = context_owned.get();
2639 FakeOutputSurfaceClient output_surface_client;
2640 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
2641 context_owned.PassAs<TestWebGraphicsContext3D>()));
2642 CHECK(output_surface->BindToClient(&output_surface_client));
2644 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
2645 output_surface.get(), shared_bitmap_manager_.get(), 0, false, 1, false));
2647 gfx::Size size(2, 2);
2648 gfx::Vector2d offset(0, 0);
2649 gfx::Rect rect(0, 0, 2, 2);
2650 ResourceFormat format = RGBA_8888;
2651 ResourceProvider::ResourceId id = 0;
2652 uint8_t pixels[16] = { 0 };
2653 int texture_id = 123;
2655 // Lazy allocation. Don't allocate when creating the resource.
2656 id = resource_provider->CreateResource(
2657 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
2659 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
2660 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(1);
2661 resource_provider->CreateForTesting(id);
2663 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
2664 resource_provider->DeleteResource(id);
2666 Mock::VerifyAndClearExpectations(context);
2668 // Do allocate when we set the pixels.
2669 id = resource_provider->CreateResource(
2670 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
2672 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
2673 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(3);
2674 EXPECT_CALL(*context, texImage2D(_, _, _, 2, 2, _, _, _, _)).Times(1);
2675 EXPECT_CALL(*context, texSubImage2D(_, _, _, _, 2, 2, _, _, _)).Times(1);
2676 resource_provider->SetPixels(id, pixels, rect, rect, offset);
2678 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
2679 resource_provider->DeleteResource(id);
2681 Mock::VerifyAndClearExpectations(context);
2683 // Same for async version.
2684 id = resource_provider->CreateResource(
2685 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
2686 resource_provider->AcquirePixelRasterBuffer(id);
2688 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
2689 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
2690 EXPECT_CALL(*context, asyncTexImage2DCHROMIUM(_, _, _, 2, 2, _, _, _, _))
2691 .Times(1);
2692 resource_provider->BeginSetPixels(id);
2693 ASSERT_TRUE(resource_provider->DidSetPixelsComplete(id));
2695 resource_provider->ReleasePixelRasterBuffer(id);
2697 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
2698 resource_provider->DeleteResource(id);
2700 Mock::VerifyAndClearExpectations(context);
2703 TEST_P(ResourceProviderTest, TextureAllocationStorageUsageAny) {
2704 // Only for GL textures.
2705 if (GetParam() != ResourceProvider::GLTexture)
2706 return;
2707 scoped_ptr<AllocationTrackingContext3D> context_owned(
2708 new StrictMock<AllocationTrackingContext3D>);
2709 AllocationTrackingContext3D* context = context_owned.get();
2710 context->set_support_texture_storage(true);
2712 FakeOutputSurfaceClient output_surface_client;
2713 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
2714 context_owned.PassAs<TestWebGraphicsContext3D>()));
2715 CHECK(output_surface->BindToClient(&output_surface_client));
2717 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
2718 output_surface.get(), shared_bitmap_manager_.get(), 0, false, 1, false));
2720 gfx::Size size(2, 2);
2721 ResourceFormat format = RGBA_8888;
2722 ResourceProvider::ResourceId id = 0;
2723 int texture_id = 123;
2725 // Lazy allocation. Don't allocate when creating the resource.
2726 id = resource_provider->CreateResource(
2727 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
2729 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
2730 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
2731 EXPECT_CALL(*context, texStorage2DEXT(_, _, _, 2, 2)).Times(1);
2732 resource_provider->AllocateForTesting(id);
2734 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
2735 resource_provider->DeleteResource(id);
2737 Mock::VerifyAndClearExpectations(context);
2740 TEST_P(ResourceProviderTest, TextureAllocationStorageUsageFramebuffer) {
2741 // Only for GL textures.
2742 if (GetParam() != ResourceProvider::GLTexture)
2743 return;
2744 scoped_ptr<AllocationTrackingContext3D> context_owned(
2745 new StrictMock<AllocationTrackingContext3D>);
2746 AllocationTrackingContext3D* context = context_owned.get();
2747 context->set_support_texture_storage(true);
2749 FakeOutputSurfaceClient output_surface_client;
2750 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
2751 context_owned.PassAs<TestWebGraphicsContext3D>()));
2752 CHECK(output_surface->BindToClient(&output_surface_client));
2754 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
2755 output_surface.get(), shared_bitmap_manager_.get(), 0, false, 1, false));
2757 gfx::Size size(2, 2);
2758 ResourceFormat format = RGBA_8888;
2759 ResourceProvider::ResourceId id = 0;
2760 int texture_id = 123;
2762 // Lazy allocation. Don't allocate when creating the resource.
2763 id = resource_provider->CreateResource(
2764 size,
2765 GL_CLAMP_TO_EDGE,
2766 ResourceProvider::TextureUsageFramebuffer,
2767 format);
2769 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
2770 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
2771 EXPECT_CALL(*context, texImage2D(_, _, _, 2, 2, _, _, _, _)).Times(1);
2772 resource_provider->AllocateForTesting(id);
2774 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
2775 resource_provider->DeleteResource(id);
2777 Mock::VerifyAndClearExpectations(context);
2780 TEST_P(ResourceProviderTest, PixelBuffer_GLTexture) {
2781 if (GetParam() != ResourceProvider::GLTexture)
2782 return;
2783 scoped_ptr<AllocationTrackingContext3D> context_owned(
2784 new StrictMock<AllocationTrackingContext3D>);
2785 AllocationTrackingContext3D* context = context_owned.get();
2787 FakeOutputSurfaceClient output_surface_client;
2788 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
2789 context_owned.PassAs<TestWebGraphicsContext3D>()));
2790 CHECK(output_surface->BindToClient(&output_surface_client));
2792 gfx::Size size(2, 2);
2793 ResourceFormat format = RGBA_8888;
2794 ResourceProvider::ResourceId id = 0;
2795 int texture_id = 123;
2797 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
2798 output_surface.get(), shared_bitmap_manager_.get(), 0, false, 1, false));
2800 id = resource_provider->CreateResource(
2801 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
2802 resource_provider->AcquirePixelRasterBuffer(id);
2804 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
2805 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
2806 EXPECT_CALL(*context, asyncTexImage2DCHROMIUM(_, _, _, 2, 2, _, _, _, _))
2807 .Times(1);
2808 resource_provider->BeginSetPixels(id);
2810 EXPECT_TRUE(resource_provider->DidSetPixelsComplete(id));
2812 resource_provider->ReleasePixelRasterBuffer(id);
2814 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
2815 resource_provider->DeleteResource(id);
2817 Mock::VerifyAndClearExpectations(context);
2820 TEST_P(ResourceProviderTest, ForcingAsyncUploadToComplete) {
2821 // Only for GL textures.
2822 if (GetParam() != ResourceProvider::GLTexture)
2823 return;
2824 scoped_ptr<AllocationTrackingContext3D> context_owned(
2825 new StrictMock<AllocationTrackingContext3D>);
2826 AllocationTrackingContext3D* context = context_owned.get();
2828 FakeOutputSurfaceClient output_surface_client;
2829 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
2830 context_owned.PassAs<TestWebGraphicsContext3D>()));
2831 CHECK(output_surface->BindToClient(&output_surface_client));
2833 gfx::Size size(2, 2);
2834 ResourceFormat format = RGBA_8888;
2835 ResourceProvider::ResourceId id = 0;
2836 int texture_id = 123;
2838 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
2839 output_surface.get(), shared_bitmap_manager_.get(), 0, false, 1, false));
2841 id = resource_provider->CreateResource(
2842 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
2843 resource_provider->AcquirePixelRasterBuffer(id);
2845 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
2846 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
2847 EXPECT_CALL(*context, asyncTexImage2DCHROMIUM(_, _, _, 2, 2, _, _, _, _))
2848 .Times(1);
2849 resource_provider->BeginSetPixels(id);
2851 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(1);
2852 EXPECT_CALL(*context, waitAsyncTexImage2DCHROMIUM(GL_TEXTURE_2D)).Times(1);
2853 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, 0)).Times(1);
2854 resource_provider->ForceSetPixelsToComplete(id);
2856 resource_provider->ReleasePixelRasterBuffer(id);
2858 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
2859 resource_provider->DeleteResource(id);
2861 Mock::VerifyAndClearExpectations(context);
2864 TEST_P(ResourceProviderTest, PixelBufferLostContext) {
2865 scoped_ptr<AllocationTrackingContext3D> context_owned(
2866 new NiceMock<AllocationTrackingContext3D>);
2867 AllocationTrackingContext3D* context = context_owned.get();
2869 FakeOutputSurfaceClient output_surface_client;
2870 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
2871 context_owned.PassAs<TestWebGraphicsContext3D>()));
2872 CHECK(output_surface->BindToClient(&output_surface_client));
2874 gfx::Size size(2, 2);
2875 ResourceFormat format = RGBA_8888;
2876 ResourceProvider::ResourceId id = 0;
2877 int texture_id = 123;
2879 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
2880 output_surface.get(), shared_bitmap_manager_.get(), 0, false, 1, false));
2882 EXPECT_CALL(*context, NextTextureId()).WillRepeatedly(Return(texture_id));
2884 id = resource_provider->CreateResource(
2885 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
2886 context->loseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB,
2887 GL_INNOCENT_CONTEXT_RESET_ARB);
2889 resource_provider->AcquirePixelRasterBuffer(id);
2890 SkCanvas* raster_canvas = resource_provider->MapPixelRasterBuffer(id);
2891 EXPECT_TRUE(raster_canvas == NULL);
2892 resource_provider->UnmapPixelRasterBuffer(id);
2893 resource_provider->ReleasePixelRasterBuffer(id);
2894 Mock::VerifyAndClearExpectations(context);
2897 TEST_P(ResourceProviderTest, Image_GLTexture) {
2898 // Only for GL textures.
2899 if (GetParam() != ResourceProvider::GLTexture)
2900 return;
2901 scoped_ptr<AllocationTrackingContext3D> context_owned(
2902 new StrictMock<AllocationTrackingContext3D>);
2903 AllocationTrackingContext3D* context = context_owned.get();
2905 FakeOutputSurfaceClient output_surface_client;
2906 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
2907 context_owned.PassAs<TestWebGraphicsContext3D>()));
2908 CHECK(output_surface->BindToClient(&output_surface_client));
2910 const int kWidth = 2;
2911 const int kHeight = 2;
2912 gfx::Size size(kWidth, kHeight);
2913 ResourceFormat format = RGBA_8888;
2914 ResourceProvider::ResourceId id = 0;
2915 const unsigned kTextureId = 123u;
2916 const unsigned kImageId = 234u;
2918 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
2919 output_surface.get(), shared_bitmap_manager_.get(), 0, false, 1, false));
2921 id = resource_provider->CreateResource(
2922 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
2924 const int kStride = 4;
2925 void* dummy_mapped_buffer_address = NULL;
2926 EXPECT_CALL(
2927 *context,
2928 createImageCHROMIUM(kWidth, kHeight, GL_RGBA8_OES, GL_IMAGE_MAP_CHROMIUM))
2929 .WillOnce(Return(kImageId))
2930 .RetiresOnSaturation();
2931 EXPECT_CALL(*context, getImageParameterivCHROMIUM(kImageId,
2932 GL_IMAGE_ROWBYTES_CHROMIUM,
2934 .WillOnce(SetArgPointee<2>(kStride))
2935 .RetiresOnSaturation();
2936 EXPECT_CALL(*context, mapImageCHROMIUM(kImageId))
2937 .WillOnce(Return(dummy_mapped_buffer_address))
2938 .RetiresOnSaturation();
2939 resource_provider->MapImageRasterBuffer(id);
2941 EXPECT_CALL(*context, unmapImageCHROMIUM(kImageId))
2942 .Times(1)
2943 .RetiresOnSaturation();
2944 resource_provider->UnmapImageRasterBuffer(id);
2946 EXPECT_CALL(*context, NextTextureId())
2947 .WillOnce(Return(kTextureId))
2948 .RetiresOnSaturation();
2949 // Once in CreateTextureId and once in BindForSampling
2950 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kTextureId)).Times(2)
2951 .RetiresOnSaturation();
2952 EXPECT_CALL(*context, bindTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId))
2953 .Times(1)
2954 .RetiresOnSaturation();
2956 ResourceProvider::ScopedSamplerGL lock_gl(
2957 resource_provider.get(), id, GL_TEXTURE_2D, GL_LINEAR);
2958 EXPECT_EQ(kTextureId, lock_gl.texture_id());
2961 EXPECT_CALL(
2962 *context,
2963 getImageParameterivCHROMIUM(kImageId, GL_IMAGE_ROWBYTES_CHROMIUM, _))
2964 .WillOnce(SetArgPointee<2>(kStride))
2965 .RetiresOnSaturation();
2966 EXPECT_CALL(*context, mapImageCHROMIUM(kImageId))
2967 .WillOnce(Return(dummy_mapped_buffer_address))
2968 .RetiresOnSaturation();
2969 resource_provider->MapImageRasterBuffer(id);
2971 EXPECT_CALL(*context, unmapImageCHROMIUM(kImageId))
2972 .Times(1)
2973 .RetiresOnSaturation();
2974 resource_provider->UnmapImageRasterBuffer(id);
2976 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kTextureId)).Times(1)
2977 .RetiresOnSaturation();
2978 EXPECT_CALL(*context, releaseTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId))
2979 .Times(1)
2980 .RetiresOnSaturation();
2981 EXPECT_CALL(*context, bindTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId))
2982 .Times(1)
2983 .RetiresOnSaturation();
2984 EXPECT_CALL(*context, RetireTextureId(kTextureId))
2985 .Times(1)
2986 .RetiresOnSaturation();
2988 ResourceProvider::ScopedSamplerGL lock_gl(
2989 resource_provider.get(), id, GL_TEXTURE_2D, GL_LINEAR);
2990 EXPECT_EQ(kTextureId, lock_gl.texture_id());
2993 EXPECT_CALL(*context, destroyImageCHROMIUM(kImageId))
2994 .Times(1)
2995 .RetiresOnSaturation();
2998 TEST_P(ResourceProviderTest, Image_Bitmap) {
2999 if (GetParam() != ResourceProvider::Bitmap)
3000 return;
3001 FakeOutputSurfaceClient output_surface_client;
3002 scoped_ptr<OutputSurface> output_surface(
3003 FakeOutputSurface::CreateSoftware(make_scoped_ptr(
3004 new SoftwareOutputDevice)));
3005 CHECK(output_surface->BindToClient(&output_surface_client));
3007 gfx::Size size(1, 1);
3008 ResourceFormat format = RGBA_8888;
3009 ResourceProvider::ResourceId id = 0;
3010 const uint32_t kBadBeef = 0xbadbeef;
3012 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
3013 output_surface.get(), shared_bitmap_manager_.get(), 0, false, 1, false));
3015 id = resource_provider->CreateResource(
3016 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
3018 SkBitmap bitmap;
3019 bitmap.allocN32Pixels(size.width(), size.height());
3020 *(bitmap.getAddr32(0, 0)) = kBadBeef;
3021 SkCanvas* canvas = resource_provider->MapImageRasterBuffer(id);
3022 ASSERT_TRUE(!!canvas);
3023 canvas->writePixels(bitmap, 0, 0);
3024 resource_provider->UnmapImageRasterBuffer(id);
3027 ResourceProvider::ScopedReadLockSoftware lock(resource_provider.get(), id);
3028 const SkBitmap* sk_bitmap = lock.sk_bitmap();
3029 EXPECT_EQ(sk_bitmap->width(), size.width());
3030 EXPECT_EQ(sk_bitmap->height(), size.height());
3031 EXPECT_EQ(*sk_bitmap->getAddr32(0, 0), kBadBeef);
3034 resource_provider->DeleteResource(id);
3037 TEST_P(ResourceProviderTest, CopyResource_GLTexture) {
3038 if (GetParam() != ResourceProvider::GLTexture)
3039 return;
3040 scoped_ptr<AllocationTrackingContext3D> context_owned(
3041 new StrictMock<AllocationTrackingContext3D>);
3042 AllocationTrackingContext3D* context = context_owned.get();
3043 context_owned->set_support_sync_query(true);
3045 FakeOutputSurfaceClient output_surface_client;
3046 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
3047 context_owned.PassAs<TestWebGraphicsContext3D>()));
3048 ASSERT_TRUE(output_surface->BindToClient(&output_surface_client));
3050 const int kWidth = 2;
3051 const int kHeight = 2;
3052 gfx::Size size(kWidth, kHeight);
3053 ResourceFormat format = RGBA_8888;
3054 ResourceProvider::ResourceId source_id = 0;
3055 ResourceProvider::ResourceId dest_id = 0;
3056 const unsigned kSourceTextureId = 123u;
3057 const unsigned kDestTextureId = 321u;
3058 const unsigned kImageId = 234u;
3060 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
3061 output_surface.get(), shared_bitmap_manager_.get(), 0, false, 1, false));
3063 source_id = resource_provider->CreateResource(
3064 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
3066 const int kStride = 4;
3067 void* dummy_mapped_buffer_address = NULL;
3068 EXPECT_CALL(
3069 *context,
3070 createImageCHROMIUM(kWidth, kHeight, GL_RGBA8_OES, GL_IMAGE_MAP_CHROMIUM))
3071 .WillOnce(Return(kImageId))
3072 .RetiresOnSaturation();
3073 EXPECT_CALL(
3074 *context,
3075 getImageParameterivCHROMIUM(kImageId, GL_IMAGE_ROWBYTES_CHROMIUM, _))
3076 .WillOnce(SetArgPointee<2>(kStride))
3077 .RetiresOnSaturation();
3078 EXPECT_CALL(*context, mapImageCHROMIUM(kImageId))
3079 .WillOnce(Return(dummy_mapped_buffer_address))
3080 .RetiresOnSaturation();
3081 resource_provider->MapImageRasterBuffer(source_id);
3082 Mock::VerifyAndClearExpectations(context);
3084 EXPECT_CALL(*context, unmapImageCHROMIUM(kImageId))
3085 .Times(1)
3086 .RetiresOnSaturation();
3087 resource_provider->UnmapImageRasterBuffer(source_id);
3088 Mock::VerifyAndClearExpectations(context);
3090 dest_id = resource_provider->CreateResource(
3091 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
3093 EXPECT_CALL(*context, NextTextureId())
3094 .WillOnce(Return(kDestTextureId))
3095 .RetiresOnSaturation();
3096 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kDestTextureId))
3097 .Times(1)
3098 .RetiresOnSaturation();
3099 EXPECT_CALL(*context, NextTextureId())
3100 .WillOnce(Return(kSourceTextureId))
3101 .RetiresOnSaturation();
3102 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kSourceTextureId))
3103 .Times(2)
3104 .RetiresOnSaturation();
3105 EXPECT_CALL(*context, bindTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId))
3106 .Times(1)
3107 .RetiresOnSaturation();
3108 resource_provider->CopyResource(source_id, dest_id);
3109 Mock::VerifyAndClearExpectations(context);
3111 EXPECT_CALL(*context, destroyImageCHROMIUM(kImageId))
3112 .Times(1)
3113 .RetiresOnSaturation();
3114 EXPECT_CALL(*context, RetireTextureId(kSourceTextureId))
3115 .Times(1)
3116 .RetiresOnSaturation();
3117 EXPECT_CALL(*context, RetireTextureId(kDestTextureId))
3118 .Times(1)
3119 .RetiresOnSaturation();
3120 resource_provider->DeleteResource(source_id);
3121 resource_provider->DeleteResource(dest_id);
3124 TEST_P(ResourceProviderTest, CopyResource_Bitmap) {
3125 if (GetParam() != ResourceProvider::Bitmap)
3126 return;
3127 FakeOutputSurfaceClient output_surface_client;
3128 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::CreateSoftware(
3129 make_scoped_ptr(new SoftwareOutputDevice)));
3130 CHECK(output_surface->BindToClient(&output_surface_client));
3132 gfx::Size size(1, 1);
3133 ResourceFormat format = RGBA_8888;
3134 ResourceProvider::ResourceId source_id = 0;
3135 ResourceProvider::ResourceId dest_id = 0;
3136 const uint32_t kBadBeef = 0xbadbeef;
3138 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
3139 output_surface.get(), shared_bitmap_manager_.get(), 0, false, 1, false));
3141 source_id = resource_provider->CreateResource(
3142 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
3144 SkBitmap bitmap;
3145 bitmap.allocN32Pixels(size.width(), size.height());
3146 *(bitmap.getAddr32(0, 0)) = kBadBeef;
3147 SkCanvas* canvas = resource_provider->MapImageRasterBuffer(source_id);
3148 ASSERT_TRUE(!!canvas);
3149 canvas->writePixels(bitmap, 0, 0);
3150 resource_provider->UnmapImageRasterBuffer(source_id);
3152 dest_id = resource_provider->CreateResource(
3153 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
3155 resource_provider->CopyResource(source_id, dest_id);
3158 ResourceProvider::ScopedReadLockSoftware lock(resource_provider.get(),
3159 dest_id);
3160 const SkBitmap* sk_bitmap = lock.sk_bitmap();
3161 EXPECT_EQ(sk_bitmap->width(), size.width());
3162 EXPECT_EQ(sk_bitmap->height(), size.height());
3163 EXPECT_EQ(*sk_bitmap->getAddr32(0, 0), kBadBeef);
3166 resource_provider->DeleteResource(source_id);
3167 resource_provider->DeleteResource(dest_id);
3170 void InitializeGLAndCheck(ContextSharedData* shared_data,
3171 ResourceProvider* resource_provider,
3172 FakeOutputSurface* output_surface) {
3173 scoped_ptr<ResourceProviderContext> context_owned =
3174 ResourceProviderContext::Create(shared_data);
3175 ResourceProviderContext* context = context_owned.get();
3177 scoped_refptr<TestContextProvider> context_provider =
3178 TestContextProvider::Create(
3179 context_owned.PassAs<TestWebGraphicsContext3D>());
3180 output_surface->InitializeAndSetContext3d(context_provider);
3181 resource_provider->InitializeGL();
3183 CheckCreateResource(ResourceProvider::GLTexture, resource_provider, context);
3186 TEST(ResourceProviderTest, BasicInitializeGLSoftware) {
3187 scoped_ptr<ContextSharedData> shared_data = ContextSharedData::Create();
3188 bool delegated_rendering = false;
3189 scoped_ptr<FakeOutputSurface> output_surface(
3190 FakeOutputSurface::CreateDeferredGL(
3191 scoped_ptr<SoftwareOutputDevice>(new SoftwareOutputDevice),
3192 delegated_rendering));
3193 FakeOutputSurfaceClient client(output_surface.get());
3194 EXPECT_TRUE(output_surface->BindToClient(&client));
3195 scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
3196 new TestSharedBitmapManager());
3197 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
3198 output_surface.get(), shared_bitmap_manager.get(), 0, false, 1, false));
3200 CheckCreateResource(ResourceProvider::Bitmap, resource_provider.get(), NULL);
3202 InitializeGLAndCheck(shared_data.get(),
3203 resource_provider.get(),
3204 output_surface.get());
3206 resource_provider->InitializeSoftware();
3207 output_surface->ReleaseGL();
3208 CheckCreateResource(ResourceProvider::Bitmap, resource_provider.get(), NULL);
3210 InitializeGLAndCheck(shared_data.get(),
3211 resource_provider.get(),
3212 output_surface.get());
3215 TEST_P(ResourceProviderTest, CompressedTextureETC1Allocate) {
3216 if (GetParam() != ResourceProvider::GLTexture)
3217 return;
3219 scoped_ptr<AllocationTrackingContext3D> context_owned(
3220 new AllocationTrackingContext3D);
3221 AllocationTrackingContext3D* context = context_owned.get();
3222 context_owned->set_support_compressed_texture_etc1(true);
3224 FakeOutputSurfaceClient output_surface_client;
3225 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
3226 context_owned.PassAs<TestWebGraphicsContext3D>()));
3227 CHECK(output_surface->BindToClient(&output_surface_client));
3229 gfx::Size size(4, 4);
3230 scoped_ptr<ResourceProvider> resource_provider(
3231 ResourceProvider::Create(output_surface.get(),
3232 shared_bitmap_manager_.get(),
3234 false,
3236 false));
3237 int texture_id = 123;
3239 ResourceProvider::ResourceId id = resource_provider->CreateResource(
3240 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, ETC1);
3241 EXPECT_NE(0u, id);
3242 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3243 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
3244 resource_provider->AllocateForTesting(id);
3246 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3247 resource_provider->DeleteResource(id);
3250 TEST_P(ResourceProviderTest, CompressedTextureETC1SetPixels) {
3251 if (GetParam() != ResourceProvider::GLTexture)
3252 return;
3254 scoped_ptr<AllocationTrackingContext3D> context_owned(
3255 new AllocationTrackingContext3D);
3256 AllocationTrackingContext3D* context = context_owned.get();
3257 context_owned->set_support_compressed_texture_etc1(true);
3259 FakeOutputSurfaceClient output_surface_client;
3260 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
3261 context_owned.PassAs<TestWebGraphicsContext3D>()));
3262 CHECK(output_surface->BindToClient(&output_surface_client));
3264 gfx::Size size(4, 4);
3265 scoped_ptr<ResourceProvider> resource_provider(
3266 ResourceProvider::Create(output_surface.get(),
3267 shared_bitmap_manager_.get(),
3269 false,
3271 false));
3272 int texture_id = 123;
3273 uint8_t pixels[8];
3275 ResourceProvider::ResourceId id = resource_provider->CreateResource(
3276 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, ETC1);
3277 EXPECT_NE(0u, id);
3278 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3279 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(3);
3280 EXPECT_CALL(*context,
3281 compressedTexImage2D(
3282 _, 0, _, size.width(), size.height(), _, _, _)).Times(1);
3283 resource_provider->SetPixels(
3284 id, pixels, gfx::Rect(size), gfx::Rect(size), gfx::Vector2d(0, 0));
3286 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3287 resource_provider->DeleteResource(id);
3290 INSTANTIATE_TEST_CASE_P(
3291 ResourceProviderTests,
3292 ResourceProviderTest,
3293 ::testing::Values(ResourceProvider::GLTexture, ResourceProvider::Bitmap));
3295 class TextureIdAllocationTrackingContext : public TestWebGraphicsContext3D {
3296 public:
3297 virtual GLuint NextTextureId() OVERRIDE {
3298 base::AutoLock lock(namespace_->lock);
3299 return namespace_->next_texture_id++;
3301 virtual void RetireTextureId(GLuint) OVERRIDE {}
3302 GLuint PeekTextureId() {
3303 base::AutoLock lock(namespace_->lock);
3304 return namespace_->next_texture_id;
3308 TEST(ResourceProviderTest, TextureAllocationChunkSize) {
3309 scoped_ptr<TextureIdAllocationTrackingContext> context_owned(
3310 new TextureIdAllocationTrackingContext);
3311 TextureIdAllocationTrackingContext* context = context_owned.get();
3313 FakeOutputSurfaceClient output_surface_client;
3314 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
3315 context_owned.PassAs<TestWebGraphicsContext3D>()));
3316 CHECK(output_surface->BindToClient(&output_surface_client));
3317 scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
3318 new TestSharedBitmapManager());
3320 gfx::Size size(1, 1);
3321 ResourceFormat format = RGBA_8888;
3324 size_t kTextureAllocationChunkSize = 1;
3325 scoped_ptr<ResourceProvider> resource_provider(
3326 ResourceProvider::Create(output_surface.get(),
3327 shared_bitmap_manager.get(),
3329 false,
3330 kTextureAllocationChunkSize,
3331 false));
3333 ResourceProvider::ResourceId id = resource_provider->CreateResource(
3334 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
3335 resource_provider->AllocateForTesting(id);
3336 Mock::VerifyAndClearExpectations(context);
3338 DCHECK_EQ(2u, context->PeekTextureId());
3339 resource_provider->DeleteResource(id);
3343 size_t kTextureAllocationChunkSize = 8;
3344 scoped_ptr<ResourceProvider> resource_provider(
3345 ResourceProvider::Create(output_surface.get(),
3346 shared_bitmap_manager.get(),
3348 false,
3349 kTextureAllocationChunkSize,
3350 false));
3352 ResourceProvider::ResourceId id = resource_provider->CreateResource(
3353 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
3354 resource_provider->AllocateForTesting(id);
3355 Mock::VerifyAndClearExpectations(context);
3357 DCHECK_EQ(10u, context->PeekTextureId());
3358 resource_provider->DeleteResource(id);
3362 } // namespace
3363 } // namespace cc