Update mojo surfaces bindings and mojo/cc/ glue
[chromium-blink-merge.git] / cc / resources / resource_provider_unittest.cc
blob18e3e9a3bdd0926d3af97b721ad99831e2398f18
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 resource_provider->WaitSyncPointIfNeeded(id);
343 switch (resource_provider->default_resource_type()) {
344 case ResourceProvider::GLTexture: {
345 ResourceProvider::ScopedReadLockGL lock_gl(resource_provider, id);
346 ASSERT_NE(0U, lock_gl.texture_id());
347 context->bindTexture(GL_TEXTURE_2D, lock_gl.texture_id());
348 context->GetPixels(size, format, pixels);
349 break;
351 case ResourceProvider::Bitmap: {
352 ResourceProvider::ScopedReadLockSoftware lock_software(resource_provider,
353 id);
354 memcpy(pixels,
355 lock_software.sk_bitmap()->getPixels(),
356 lock_software.sk_bitmap()->getSize());
357 break;
359 case ResourceProvider::InvalidType:
360 NOTREACHED();
361 break;
365 class ResourceProviderTest
366 : public testing::TestWithParam<ResourceProvider::ResourceType> {
367 public:
368 ResourceProviderTest()
369 : shared_data_(ContextSharedData::Create()),
370 context3d_(NULL),
371 child_context_(NULL) {
372 switch (GetParam()) {
373 case ResourceProvider::GLTexture: {
374 scoped_ptr<ResourceProviderContext> context3d(
375 ResourceProviderContext::Create(shared_data_.get()));
376 context3d_ = context3d.get();
378 scoped_refptr<TestContextProvider> context_provider =
379 TestContextProvider::Create(
380 context3d.PassAs<TestWebGraphicsContext3D>());
382 output_surface_ = FakeOutputSurface::Create3d(context_provider);
384 scoped_ptr<ResourceProviderContext> child_context_owned =
385 ResourceProviderContext::Create(shared_data_.get());
386 child_context_ = child_context_owned.get();
387 child_output_surface_ = FakeOutputSurface::Create3d(
388 child_context_owned.PassAs<TestWebGraphicsContext3D>());
389 break;
391 case ResourceProvider::Bitmap:
392 output_surface_ = FakeOutputSurface::CreateSoftware(
393 make_scoped_ptr(new SoftwareOutputDevice));
394 child_output_surface_ = FakeOutputSurface::CreateSoftware(
395 make_scoped_ptr(new SoftwareOutputDevice));
396 break;
397 case ResourceProvider::InvalidType:
398 NOTREACHED();
399 break;
401 CHECK(output_surface_->BindToClient(&output_surface_client_));
402 CHECK(child_output_surface_->BindToClient(&child_output_surface_client_));
404 shared_bitmap_manager_.reset(new TestSharedBitmapManager());
406 resource_provider_ = ResourceProvider::Create(
407 output_surface_.get(), shared_bitmap_manager_.get(), 0, false, 1,
408 false);
409 child_resource_provider_ = ResourceProvider::Create(
410 child_output_surface_.get(),
411 shared_bitmap_manager_.get(),
413 false,
415 false);
418 static void CollectResources(ReturnedResourceArray* array,
419 const ReturnedResourceArray& returned) {
420 array->insert(array->end(), returned.begin(), returned.end());
423 static ReturnCallback GetReturnCallback(ReturnedResourceArray* array) {
424 return base::Bind(&ResourceProviderTest::CollectResources, array);
427 static void SetResourceFilter(ResourceProvider* resource_provider,
428 ResourceProvider::ResourceId id,
429 GLenum filter) {
430 ResourceProvider::ScopedSamplerGL sampler(
431 resource_provider, id, GL_TEXTURE_2D, filter);
434 ResourceProviderContext* context() { return context3d_; }
436 ResourceProvider::ResourceId CreateChildMailbox(uint32* release_sync_point,
437 bool* lost_resource,
438 bool* release_called,
439 uint32* sync_point) {
440 if (GetParam() == ResourceProvider::GLTexture) {
441 unsigned texture = child_context_->createTexture();
442 gpu::Mailbox gpu_mailbox;
443 child_context_->bindTexture(GL_TEXTURE_2D, texture);
444 child_context_->genMailboxCHROMIUM(gpu_mailbox.name);
445 child_context_->produceTextureCHROMIUM(GL_TEXTURE_2D, gpu_mailbox.name);
446 *sync_point = child_context_->insertSyncPoint();
447 EXPECT_LT(0u, *sync_point);
449 scoped_ptr<base::SharedMemory> shared_memory;
450 scoped_ptr<SingleReleaseCallback> callback =
451 SingleReleaseCallback::Create(base::Bind(ReleaseSharedMemoryCallback,
452 base::Passed(&shared_memory),
453 release_called,
454 release_sync_point,
455 lost_resource));
456 return child_resource_provider_->CreateResourceFromTextureMailbox(
457 TextureMailbox(gpu_mailbox, GL_TEXTURE_2D, *sync_point),
458 callback.Pass());
459 } else {
460 gfx::Size size(64, 64);
461 scoped_ptr<base::SharedMemory> shared_memory(
462 CreateAndFillSharedMemory(size, 0));
464 base::SharedMemory* shared_memory_ptr = shared_memory.get();
465 scoped_ptr<SingleReleaseCallback> callback =
466 SingleReleaseCallback::Create(base::Bind(ReleaseSharedMemoryCallback,
467 base::Passed(&shared_memory),
468 release_called,
469 release_sync_point,
470 lost_resource));
471 return child_resource_provider_->CreateResourceFromTextureMailbox(
472 TextureMailbox(shared_memory_ptr, size), callback.Pass());
476 protected:
477 scoped_ptr<ContextSharedData> shared_data_;
478 ResourceProviderContext* context3d_;
479 ResourceProviderContext* child_context_;
480 FakeOutputSurfaceClient output_surface_client_;
481 FakeOutputSurfaceClient child_output_surface_client_;
482 scoped_ptr<OutputSurface> output_surface_;
483 scoped_ptr<OutputSurface> child_output_surface_;
484 scoped_ptr<ResourceProvider> resource_provider_;
485 scoped_ptr<ResourceProvider> child_resource_provider_;
486 scoped_ptr<TestSharedBitmapManager> shared_bitmap_manager_;
489 void CheckCreateResource(ResourceProvider::ResourceType expected_default_type,
490 ResourceProvider* resource_provider,
491 ResourceProviderContext* context) {
492 DCHECK_EQ(expected_default_type, resource_provider->default_resource_type());
494 gfx::Size size(1, 1);
495 ResourceFormat format = RGBA_8888;
496 size_t pixel_size = TextureSizeBytes(size, format);
497 ASSERT_EQ(4U, pixel_size);
499 ResourceProvider::ResourceId id = resource_provider->CreateResource(
500 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
501 EXPECT_EQ(1, static_cast<int>(resource_provider->num_resources()));
502 if (expected_default_type == ResourceProvider::GLTexture)
503 EXPECT_EQ(0u, context->NumTextures());
505 uint8_t data[4] = { 1, 2, 3, 4 };
506 gfx::Rect rect(size);
507 resource_provider->SetPixels(id, data, rect, rect, gfx::Vector2d());
508 if (expected_default_type == ResourceProvider::GLTexture)
509 EXPECT_EQ(1u, context->NumTextures());
511 uint8_t result[4] = { 0 };
512 GetResourcePixels(resource_provider, context, id, size, format, result);
513 EXPECT_EQ(0, memcmp(data, result, pixel_size));
515 resource_provider->DeleteResource(id);
516 EXPECT_EQ(0, static_cast<int>(resource_provider->num_resources()));
517 if (expected_default_type == ResourceProvider::GLTexture)
518 EXPECT_EQ(0u, context->NumTextures());
521 TEST_P(ResourceProviderTest, Basic) {
522 CheckCreateResource(GetParam(), resource_provider_.get(), context());
525 TEST_P(ResourceProviderTest, Upload) {
526 gfx::Size size(2, 2);
527 ResourceFormat format = RGBA_8888;
528 size_t pixel_size = TextureSizeBytes(size, format);
529 ASSERT_EQ(16U, pixel_size);
531 ResourceProvider::ResourceId id = resource_provider_->CreateResource(
532 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
534 uint8_t image[16] = { 0 };
535 gfx::Rect image_rect(size);
536 resource_provider_->SetPixels(
537 id, image, image_rect, image_rect, gfx::Vector2d());
539 for (uint8_t i = 0; i < pixel_size; ++i)
540 image[i] = i;
542 uint8_t result[16] = { 0 };
544 gfx::Rect source_rect(0, 0, 1, 1);
545 gfx::Vector2d dest_offset(0, 0);
546 resource_provider_->SetPixels(
547 id, image, image_rect, source_rect, dest_offset);
549 uint8_t expected[16] = { 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
550 GetResourcePixels(
551 resource_provider_.get(), context(), id, size, format, result);
552 EXPECT_EQ(0, memcmp(expected, result, pixel_size));
555 gfx::Rect source_rect(0, 0, 1, 1);
556 gfx::Vector2d dest_offset(1, 1);
557 resource_provider_->SetPixels(
558 id, image, image_rect, source_rect, dest_offset);
560 uint8_t expected[16] = { 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3 };
561 GetResourcePixels(
562 resource_provider_.get(), context(), id, size, format, result);
563 EXPECT_EQ(0, memcmp(expected, result, pixel_size));
566 gfx::Rect source_rect(1, 0, 1, 1);
567 gfx::Vector2d dest_offset(0, 1);
568 resource_provider_->SetPixels(
569 id, image, image_rect, source_rect, dest_offset);
571 uint8_t expected[16] = { 0, 1, 2, 3, 0, 0, 0, 0, 4, 5, 6, 7, 0, 1, 2, 3 };
572 GetResourcePixels(
573 resource_provider_.get(), context(), id, size, format, result);
574 EXPECT_EQ(0, memcmp(expected, result, pixel_size));
577 gfx::Rect offset_image_rect(gfx::Point(100, 100), size);
578 gfx::Rect source_rect(100, 100, 1, 1);
579 gfx::Vector2d dest_offset(1, 0);
580 resource_provider_->SetPixels(
581 id, image, offset_image_rect, source_rect, dest_offset);
583 uint8_t expected[16] = { 0, 1, 2, 3, 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3 };
584 GetResourcePixels(
585 resource_provider_.get(), context(), id, size, format, result);
586 EXPECT_EQ(0, memcmp(expected, result, pixel_size));
589 resource_provider_->DeleteResource(id);
592 TEST_P(ResourceProviderTest, TransferGLResources) {
593 if (GetParam() != ResourceProvider::GLTexture)
594 return;
595 gfx::Size size(1, 1);
596 ResourceFormat format = RGBA_8888;
597 size_t pixel_size = TextureSizeBytes(size, format);
598 ASSERT_EQ(4U, pixel_size);
600 ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource(
601 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
602 uint8_t data1[4] = { 1, 2, 3, 4 };
603 gfx::Rect rect(size);
604 child_resource_provider_->SetPixels(id1, data1, rect, rect, gfx::Vector2d());
606 ResourceProvider::ResourceId id2 = child_resource_provider_->CreateResource(
607 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
608 uint8_t data2[4] = { 5, 5, 5, 5 };
609 child_resource_provider_->SetPixels(id2, data2, rect, rect, gfx::Vector2d());
611 ResourceProvider::ResourceId id3 = child_resource_provider_->CreateResource(
612 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
613 child_resource_provider_->MapImageRasterBuffer(id3);
614 child_resource_provider_->UnmapImageRasterBuffer(id3);
616 GLuint external_texture_id = child_context_->createExternalTexture();
617 child_context_->bindTexture(GL_TEXTURE_EXTERNAL_OES, external_texture_id);
619 gpu::Mailbox external_mailbox;
620 child_context_->genMailboxCHROMIUM(external_mailbox.name);
621 child_context_->produceTextureCHROMIUM(GL_TEXTURE_EXTERNAL_OES,
622 external_mailbox.name);
623 const GLuint external_sync_point = child_context_->insertSyncPoint();
624 ResourceProvider::ResourceId id4 =
625 child_resource_provider_->CreateResourceFromTextureMailbox(
626 TextureMailbox(
627 external_mailbox, GL_TEXTURE_EXTERNAL_OES, external_sync_point),
628 SingleReleaseCallback::Create(base::Bind(&EmptyReleaseCallback)));
630 ReturnedResourceArray returned_to_child;
631 int child_id =
632 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
634 // Transfer some resources to the parent.
635 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
636 resource_ids_to_transfer.push_back(id1);
637 resource_ids_to_transfer.push_back(id2);
638 resource_ids_to_transfer.push_back(id3);
639 resource_ids_to_transfer.push_back(id4);
640 TransferableResourceArray list;
641 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
642 &list);
643 ASSERT_EQ(4u, list.size());
644 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
645 EXPECT_NE(0u, list[1].mailbox_holder.sync_point);
646 EXPECT_EQ(list[0].mailbox_holder.sync_point,
647 list[1].mailbox_holder.sync_point);
648 EXPECT_NE(0u, list[2].mailbox_holder.sync_point);
649 EXPECT_EQ(list[0].mailbox_holder.sync_point,
650 list[2].mailbox_holder.sync_point);
651 EXPECT_EQ(external_sync_point, list[3].mailbox_holder.sync_point);
652 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
653 list[0].mailbox_holder.texture_target);
654 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
655 list[1].mailbox_holder.texture_target);
656 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
657 list[2].mailbox_holder.texture_target);
658 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_EXTERNAL_OES),
659 list[3].mailbox_holder.texture_target);
660 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
661 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
662 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
663 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id4));
664 resource_provider_->ReceiveFromChild(child_id, list);
665 EXPECT_NE(list[0].mailbox_holder.sync_point,
666 context3d_->last_waited_sync_point());
668 resource_provider_->WaitSyncPointIfNeeded(list[0].id);
669 ResourceProvider::ScopedReadLockGL lock(resource_provider_.get(),
670 list[0].id);
672 EXPECT_EQ(list[0].mailbox_holder.sync_point,
673 context3d_->last_waited_sync_point());
674 resource_provider_->DeclareUsedResourcesFromChild(child_id,
675 resource_ids_to_transfer);
678 EXPECT_EQ(4u, resource_provider_->num_resources());
679 ResourceProvider::ResourceIdMap resource_map =
680 resource_provider_->GetChildToParentMap(child_id);
681 ResourceProvider::ResourceId mapped_id1 = resource_map[id1];
682 ResourceProvider::ResourceId mapped_id2 = resource_map[id2];
683 ResourceProvider::ResourceId mapped_id3 = resource_map[id3];
684 ResourceProvider::ResourceId mapped_id4 = resource_map[id4];
685 EXPECT_NE(0u, mapped_id1);
686 EXPECT_NE(0u, mapped_id2);
687 EXPECT_NE(0u, mapped_id3);
688 EXPECT_NE(0u, mapped_id4);
689 EXPECT_FALSE(resource_provider_->InUseByConsumer(id1));
690 EXPECT_FALSE(resource_provider_->InUseByConsumer(id2));
691 EXPECT_FALSE(resource_provider_->InUseByConsumer(id3));
692 EXPECT_FALSE(resource_provider_->InUseByConsumer(id4));
694 uint8_t result[4] = { 0 };
695 GetResourcePixels(
696 resource_provider_.get(), context(), mapped_id1, size, format, result);
697 EXPECT_EQ(0, memcmp(data1, result, pixel_size));
699 GetResourcePixels(
700 resource_provider_.get(), context(), mapped_id2, size, format, result);
701 EXPECT_EQ(0, memcmp(data2, result, pixel_size));
704 // Check that transfering again the same resource from the child to the
705 // parent works.
706 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
707 resource_ids_to_transfer.push_back(id1);
708 resource_ids_to_transfer.push_back(id2);
709 resource_ids_to_transfer.push_back(id3);
710 TransferableResourceArray list;
711 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
712 &list);
713 EXPECT_EQ(3u, list.size());
714 EXPECT_EQ(id1, list[0].id);
715 EXPECT_EQ(id2, list[1].id);
716 EXPECT_EQ(id3, list[2].id);
717 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
718 list[0].mailbox_holder.texture_target);
719 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
720 list[1].mailbox_holder.texture_target);
721 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
722 list[2].mailbox_holder.texture_target);
723 ReturnedResourceArray returned;
724 TransferableResource::ReturnResources(list, &returned);
725 child_resource_provider_->ReceiveReturnsFromParent(returned);
726 // ids were exported twice, we returned them only once, they should still
727 // be in-use.
728 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
729 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
730 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
733 EXPECT_EQ(0u, returned_to_child.size());
735 // Transfer resources back from the parent to the child. Set no resources as
736 // being in use.
737 ResourceProvider::ResourceIdArray no_resources;
738 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
740 ASSERT_EQ(4u, returned_to_child.size());
741 EXPECT_NE(0u, returned_to_child[0].sync_point);
742 EXPECT_NE(0u, returned_to_child[1].sync_point);
743 EXPECT_NE(0u, returned_to_child[2].sync_point);
744 EXPECT_NE(0u, returned_to_child[3].sync_point);
745 EXPECT_FALSE(returned_to_child[0].lost);
746 EXPECT_FALSE(returned_to_child[1].lost);
747 EXPECT_FALSE(returned_to_child[2].lost);
748 EXPECT_FALSE(returned_to_child[3].lost);
749 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
750 returned_to_child.clear();
752 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id1));
753 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id2));
754 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id3));
755 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id4));
758 child_resource_provider_->WaitSyncPointIfNeeded(id1);
759 ResourceProvider::ScopedReadLockGL lock(child_resource_provider_.get(),
760 id1);
761 ASSERT_NE(0U, lock.texture_id());
762 child_context_->bindTexture(GL_TEXTURE_2D, lock.texture_id());
763 child_context_->GetPixels(size, format, result);
764 EXPECT_EQ(0, memcmp(data1, result, pixel_size));
767 child_resource_provider_->WaitSyncPointIfNeeded(id2);
768 ResourceProvider::ScopedReadLockGL lock(child_resource_provider_.get(),
769 id2);
770 ASSERT_NE(0U, lock.texture_id());
771 child_context_->bindTexture(GL_TEXTURE_2D, lock.texture_id());
772 child_context_->GetPixels(size, format, result);
773 EXPECT_EQ(0, memcmp(data2, result, pixel_size));
776 child_resource_provider_->WaitSyncPointIfNeeded(id3);
777 ResourceProvider::ScopedReadLockGL lock(child_resource_provider_.get(),
778 id3);
779 ASSERT_NE(0U, lock.texture_id());
780 child_context_->bindTexture(GL_TEXTURE_2D, lock.texture_id());
783 // Transfer resources to the parent again.
784 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
785 resource_ids_to_transfer.push_back(id1);
786 resource_ids_to_transfer.push_back(id2);
787 resource_ids_to_transfer.push_back(id3);
788 resource_ids_to_transfer.push_back(id4);
789 TransferableResourceArray list;
790 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
791 &list);
792 ASSERT_EQ(4u, list.size());
793 EXPECT_EQ(id1, list[0].id);
794 EXPECT_EQ(id2, list[1].id);
795 EXPECT_EQ(id3, list[2].id);
796 EXPECT_EQ(id4, list[3].id);
797 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
798 EXPECT_NE(0u, list[1].mailbox_holder.sync_point);
799 EXPECT_NE(0u, list[2].mailbox_holder.sync_point);
800 EXPECT_NE(0u, list[3].mailbox_holder.sync_point);
801 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
802 list[0].mailbox_holder.texture_target);
803 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
804 list[1].mailbox_holder.texture_target);
805 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
806 list[2].mailbox_holder.texture_target);
807 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_EXTERNAL_OES),
808 list[3].mailbox_holder.texture_target);
809 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
810 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
811 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
812 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id4));
813 resource_provider_->ReceiveFromChild(child_id, list);
814 resource_provider_->DeclareUsedResourcesFromChild(child_id,
815 resource_ids_to_transfer);
818 EXPECT_EQ(0u, returned_to_child.size());
820 EXPECT_EQ(4u, resource_provider_->num_resources());
821 resource_provider_->DestroyChild(child_id);
822 EXPECT_EQ(0u, resource_provider_->num_resources());
824 ASSERT_EQ(4u, returned_to_child.size());
825 EXPECT_NE(0u, returned_to_child[0].sync_point);
826 EXPECT_NE(0u, returned_to_child[1].sync_point);
827 EXPECT_NE(0u, returned_to_child[2].sync_point);
828 EXPECT_NE(0u, returned_to_child[3].sync_point);
829 EXPECT_FALSE(returned_to_child[0].lost);
830 EXPECT_FALSE(returned_to_child[1].lost);
831 EXPECT_FALSE(returned_to_child[2].lost);
832 EXPECT_FALSE(returned_to_child[3].lost);
835 TEST_P(ResourceProviderTest, ReadLockCountStopsReturnToChildOrDelete) {
836 if (GetParam() != ResourceProvider::GLTexture)
837 return;
838 gfx::Size size(1, 1);
839 ResourceFormat format = RGBA_8888;
841 ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource(
842 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
843 uint8_t data1[4] = {1, 2, 3, 4};
844 gfx::Rect rect(size);
845 child_resource_provider_->SetPixels(id1, data1, rect, rect, gfx::Vector2d());
847 ReturnedResourceArray returned_to_child;
848 int child_id =
849 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
851 // Transfer some resources to the parent.
852 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
853 resource_ids_to_transfer.push_back(id1);
854 TransferableResourceArray list;
855 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
856 &list);
857 ASSERT_EQ(1u, list.size());
858 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
860 resource_provider_->ReceiveFromChild(child_id, list);
862 resource_provider_->WaitSyncPointIfNeeded(list[0].id);
863 ResourceProvider::ScopedReadLockGL lock(resource_provider_.get(),
864 list[0].id);
866 resource_provider_->DeclareUsedResourcesFromChild(
867 child_id, ResourceProvider::ResourceIdArray());
868 EXPECT_EQ(0u, returned_to_child.size());
871 EXPECT_EQ(1u, returned_to_child.size());
872 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
875 child_resource_provider_->WaitSyncPointIfNeeded(id1);
876 ResourceProvider::ScopedReadLockGL lock(child_resource_provider_.get(),
877 id1);
878 child_resource_provider_->DeleteResource(id1);
879 EXPECT_EQ(1u, child_resource_provider_->num_resources());
880 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
883 EXPECT_EQ(0u, child_resource_provider_->num_resources());
884 resource_provider_->DestroyChild(child_id);
887 TEST_P(ResourceProviderTest, AllowOverlayTransfersToParent) {
888 // Overlays only supported on the GL path.
889 if (GetParam() != ResourceProvider::GLTexture)
890 return;
892 uint32 sync_point = 0;
893 TextureMailbox mailbox(gpu::Mailbox::Generate(), GL_TEXTURE_2D, sync_point);
894 mailbox.set_allow_overlay(true);
895 scoped_ptr<SingleReleaseCallback> release_callback =
896 SingleReleaseCallback::Create(base::Bind(&EmptyReleaseCallback));
897 ResourceProvider::ResourceId id1 =
898 child_resource_provider_->CreateResourceFromTextureMailbox(
899 mailbox, release_callback.Pass());
901 TextureMailbox mailbox2(gpu::Mailbox::Generate(), GL_TEXTURE_2D, sync_point);
902 mailbox2.set_allow_overlay(false);
903 scoped_ptr<SingleReleaseCallback> release_callback2 =
904 SingleReleaseCallback::Create(base::Bind(&EmptyReleaseCallback));
905 ResourceProvider::ResourceId id2 =
906 child_resource_provider_->CreateResourceFromTextureMailbox(
907 mailbox2, release_callback2.Pass());
909 ReturnedResourceArray returned_to_child;
910 int child_id =
911 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
913 // Transfer some resources to the parent.
914 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
915 resource_ids_to_transfer.push_back(id1);
916 resource_ids_to_transfer.push_back(id2);
917 TransferableResourceArray list;
918 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
919 &list);
920 ASSERT_EQ(2u, list.size());
921 resource_provider_->ReceiveFromChild(child_id, list);
922 EXPECT_TRUE(resource_provider_->AllowOverlay(list[0].id));
923 EXPECT_FALSE(resource_provider_->AllowOverlay(list[1].id));
925 resource_provider_->DeclareUsedResourcesFromChild(
926 child_id, ResourceProvider::ResourceIdArray());
928 EXPECT_EQ(2u, returned_to_child.size());
929 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
931 child_resource_provider_->DeleteResource(id1);
932 child_resource_provider_->DeleteResource(id2);
933 EXPECT_EQ(0u, child_resource_provider_->num_resources());
935 resource_provider_->DestroyChild(child_id);
938 TEST_P(ResourceProviderTest, TransferSoftwareResources) {
939 if (GetParam() != ResourceProvider::Bitmap)
940 return;
942 gfx::Size size(1, 1);
943 ResourceFormat format = RGBA_8888;
944 size_t pixel_size = TextureSizeBytes(size, format);
945 ASSERT_EQ(4U, pixel_size);
947 ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource(
948 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
949 uint8_t data1[4] = { 1, 2, 3, 4 };
950 gfx::Rect rect(size);
951 child_resource_provider_->SetPixels(id1, data1, rect, rect, gfx::Vector2d());
953 ResourceProvider::ResourceId id2 = child_resource_provider_->CreateResource(
954 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
955 uint8_t data2[4] = { 5, 5, 5, 5 };
956 child_resource_provider_->SetPixels(id2, data2, rect, rect, gfx::Vector2d());
958 ResourceProvider::ResourceId id3 = child_resource_provider_->CreateResource(
959 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
960 uint8_t data3[4] = { 6, 7, 8, 9 };
961 SkImageInfo info = SkImageInfo::MakeN32Premul(size.width(), size.height());
962 SkCanvas* raster_canvas = child_resource_provider_->MapImageRasterBuffer(id3);
963 raster_canvas->writePixels(info, data3, info.minRowBytes(), 0, 0);
964 child_resource_provider_->UnmapImageRasterBuffer(id3);
966 scoped_ptr<base::SharedMemory> shared_memory(new base::SharedMemory());
967 shared_memory->CreateAndMapAnonymous(1);
968 base::SharedMemory* shared_memory_ptr = shared_memory.get();
969 ResourceProvider::ResourceId id4 =
970 child_resource_provider_->CreateResourceFromTextureMailbox(
971 TextureMailbox(shared_memory_ptr, gfx::Size(1, 1)),
972 SingleReleaseCallback::Create(base::Bind(
973 &SharedMemoryReleaseCallback, base::Passed(&shared_memory))));
975 ReturnedResourceArray returned_to_child;
976 int child_id =
977 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
979 // Transfer some resources to the parent.
980 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
981 resource_ids_to_transfer.push_back(id1);
982 resource_ids_to_transfer.push_back(id2);
983 resource_ids_to_transfer.push_back(id3);
984 resource_ids_to_transfer.push_back(id4);
985 TransferableResourceArray list;
986 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
987 &list);
988 ASSERT_EQ(4u, list.size());
989 EXPECT_EQ(0u, list[0].mailbox_holder.sync_point);
990 EXPECT_EQ(0u, list[1].mailbox_holder.sync_point);
991 EXPECT_EQ(0u, list[2].mailbox_holder.sync_point);
992 EXPECT_EQ(0u, list[3].mailbox_holder.sync_point);
993 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
994 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
995 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
996 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id4));
997 resource_provider_->ReceiveFromChild(child_id, list);
998 resource_provider_->DeclareUsedResourcesFromChild(child_id,
999 resource_ids_to_transfer);
1002 EXPECT_EQ(4u, resource_provider_->num_resources());
1003 ResourceProvider::ResourceIdMap resource_map =
1004 resource_provider_->GetChildToParentMap(child_id);
1005 ResourceProvider::ResourceId mapped_id1 = resource_map[id1];
1006 ResourceProvider::ResourceId mapped_id2 = resource_map[id2];
1007 ResourceProvider::ResourceId mapped_id3 = resource_map[id3];
1008 ResourceProvider::ResourceId mapped_id4 = resource_map[id4];
1009 EXPECT_NE(0u, mapped_id1);
1010 EXPECT_NE(0u, mapped_id2);
1011 EXPECT_NE(0u, mapped_id3);
1012 EXPECT_NE(0u, mapped_id4);
1013 EXPECT_FALSE(resource_provider_->InUseByConsumer(id1));
1014 EXPECT_FALSE(resource_provider_->InUseByConsumer(id2));
1015 EXPECT_FALSE(resource_provider_->InUseByConsumer(id3));
1016 EXPECT_FALSE(resource_provider_->InUseByConsumer(id4));
1018 uint8_t result[4] = { 0 };
1019 GetResourcePixels(
1020 resource_provider_.get(), context(), mapped_id1, size, format, result);
1021 EXPECT_EQ(0, memcmp(data1, result, pixel_size));
1023 GetResourcePixels(
1024 resource_provider_.get(), context(), mapped_id2, size, format, result);
1025 EXPECT_EQ(0, memcmp(data2, result, pixel_size));
1027 GetResourcePixels(
1028 resource_provider_.get(), context(), mapped_id3, size, format, result);
1029 EXPECT_EQ(0, memcmp(data3, result, pixel_size));
1032 // Check that transfering again the same resource from the child to the
1033 // parent works.
1034 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1035 resource_ids_to_transfer.push_back(id1);
1036 resource_ids_to_transfer.push_back(id2);
1037 resource_ids_to_transfer.push_back(id3);
1038 TransferableResourceArray list;
1039 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1040 &list);
1041 EXPECT_EQ(3u, list.size());
1042 EXPECT_EQ(id1, list[0].id);
1043 EXPECT_EQ(id2, list[1].id);
1044 EXPECT_EQ(id3, list[2].id);
1045 ReturnedResourceArray returned;
1046 TransferableResource::ReturnResources(list, &returned);
1047 child_resource_provider_->ReceiveReturnsFromParent(returned);
1048 // ids were exported twice, we returned them only once, they should still
1049 // be in-use.
1050 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1051 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
1052 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
1055 EXPECT_EQ(0u, returned_to_child.size());
1057 // Transfer resources back from the parent to the child. Set no resources as
1058 // being in use.
1059 ResourceProvider::ResourceIdArray no_resources;
1060 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
1062 ASSERT_EQ(4u, returned_to_child.size());
1063 EXPECT_EQ(0u, returned_to_child[0].sync_point);
1064 EXPECT_EQ(0u, returned_to_child[1].sync_point);
1065 EXPECT_EQ(0u, returned_to_child[2].sync_point);
1066 EXPECT_EQ(0u, returned_to_child[3].sync_point);
1067 std::set<ResourceProvider::ResourceId> expected_ids;
1068 expected_ids.insert(id1);
1069 expected_ids.insert(id2);
1070 expected_ids.insert(id3);
1071 expected_ids.insert(id4);
1072 std::set<ResourceProvider::ResourceId> returned_ids;
1073 for (unsigned i = 0; i < 4; i++)
1074 returned_ids.insert(returned_to_child[i].id);
1075 EXPECT_EQ(expected_ids, returned_ids);
1076 EXPECT_FALSE(returned_to_child[0].lost);
1077 EXPECT_FALSE(returned_to_child[1].lost);
1078 EXPECT_FALSE(returned_to_child[2].lost);
1079 EXPECT_FALSE(returned_to_child[3].lost);
1080 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
1081 returned_to_child.clear();
1083 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id1));
1084 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id2));
1085 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id3));
1086 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id4));
1089 ResourceProvider::ScopedReadLockSoftware lock(
1090 child_resource_provider_.get(), id1);
1091 const SkBitmap* sk_bitmap = lock.sk_bitmap();
1092 EXPECT_EQ(sk_bitmap->width(), size.width());
1093 EXPECT_EQ(sk_bitmap->height(), size.height());
1094 EXPECT_EQ(0, memcmp(data1, sk_bitmap->getPixels(), pixel_size));
1097 ResourceProvider::ScopedReadLockSoftware lock(
1098 child_resource_provider_.get(), id2);
1099 const SkBitmap* sk_bitmap = lock.sk_bitmap();
1100 EXPECT_EQ(sk_bitmap->width(), size.width());
1101 EXPECT_EQ(sk_bitmap->height(), size.height());
1102 EXPECT_EQ(0, memcmp(data2, sk_bitmap->getPixels(), pixel_size));
1105 ResourceProvider::ScopedReadLockSoftware lock(
1106 child_resource_provider_.get(), id3);
1107 const SkBitmap* sk_bitmap = lock.sk_bitmap();
1108 EXPECT_EQ(sk_bitmap->width(), size.width());
1109 EXPECT_EQ(sk_bitmap->height(), size.height());
1110 EXPECT_EQ(0, memcmp(data3, sk_bitmap->getPixels(), pixel_size));
1113 // Transfer resources to the parent again.
1114 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1115 resource_ids_to_transfer.push_back(id1);
1116 resource_ids_to_transfer.push_back(id2);
1117 resource_ids_to_transfer.push_back(id3);
1118 resource_ids_to_transfer.push_back(id4);
1119 TransferableResourceArray list;
1120 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1121 &list);
1122 ASSERT_EQ(4u, list.size());
1123 EXPECT_EQ(id1, list[0].id);
1124 EXPECT_EQ(id2, list[1].id);
1125 EXPECT_EQ(id3, list[2].id);
1126 EXPECT_EQ(id4, list[3].id);
1127 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1128 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
1129 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
1130 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id4));
1131 resource_provider_->ReceiveFromChild(child_id, list);
1132 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1133 resource_ids_to_transfer);
1136 EXPECT_EQ(0u, returned_to_child.size());
1138 EXPECT_EQ(4u, resource_provider_->num_resources());
1139 resource_provider_->DestroyChild(child_id);
1140 EXPECT_EQ(0u, resource_provider_->num_resources());
1142 ASSERT_EQ(4u, returned_to_child.size());
1143 EXPECT_EQ(0u, returned_to_child[0].sync_point);
1144 EXPECT_EQ(0u, returned_to_child[1].sync_point);
1145 EXPECT_EQ(0u, returned_to_child[2].sync_point);
1146 EXPECT_EQ(0u, returned_to_child[3].sync_point);
1147 std::set<ResourceProvider::ResourceId> expected_ids;
1148 expected_ids.insert(id1);
1149 expected_ids.insert(id2);
1150 expected_ids.insert(id3);
1151 expected_ids.insert(id4);
1152 std::set<ResourceProvider::ResourceId> returned_ids;
1153 for (unsigned i = 0; i < 4; i++)
1154 returned_ids.insert(returned_to_child[i].id);
1155 EXPECT_EQ(expected_ids, returned_ids);
1156 EXPECT_FALSE(returned_to_child[0].lost);
1157 EXPECT_FALSE(returned_to_child[1].lost);
1158 EXPECT_FALSE(returned_to_child[2].lost);
1159 EXPECT_FALSE(returned_to_child[3].lost);
1162 TEST_P(ResourceProviderTest, TransferGLToSoftware) {
1163 if (GetParam() != ResourceProvider::Bitmap)
1164 return;
1166 scoped_ptr<ResourceProviderContext> child_context_owned(
1167 ResourceProviderContext::Create(shared_data_.get()));
1169 FakeOutputSurfaceClient child_output_surface_client;
1170 scoped_ptr<OutputSurface> child_output_surface(FakeOutputSurface::Create3d(
1171 child_context_owned.PassAs<TestWebGraphicsContext3D>()));
1172 CHECK(child_output_surface->BindToClient(&child_output_surface_client));
1174 scoped_ptr<ResourceProvider> child_resource_provider(ResourceProvider::Create(
1175 child_output_surface.get(), shared_bitmap_manager_.get(), 0, false, 1,
1176 false));
1178 gfx::Size size(1, 1);
1179 ResourceFormat format = RGBA_8888;
1180 size_t pixel_size = TextureSizeBytes(size, format);
1181 ASSERT_EQ(4U, pixel_size);
1183 ResourceProvider::ResourceId id1 = child_resource_provider->CreateResource(
1184 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
1185 uint8_t data1[4] = { 1, 2, 3, 4 };
1186 gfx::Rect rect(size);
1187 child_resource_provider->SetPixels(id1, data1, rect, rect, gfx::Vector2d());
1189 ReturnedResourceArray returned_to_child;
1190 int child_id =
1191 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1193 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1194 resource_ids_to_transfer.push_back(id1);
1195 TransferableResourceArray list;
1196 child_resource_provider->PrepareSendToParent(resource_ids_to_transfer,
1197 &list);
1198 ASSERT_EQ(1u, list.size());
1199 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
1200 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
1201 list[0].mailbox_holder.texture_target);
1202 EXPECT_TRUE(child_resource_provider->InUseByConsumer(id1));
1203 resource_provider_->ReceiveFromChild(child_id, list);
1206 EXPECT_EQ(0u, resource_provider_->num_resources());
1207 ASSERT_EQ(1u, returned_to_child.size());
1208 EXPECT_EQ(returned_to_child[0].id, id1);
1209 ResourceProvider::ResourceIdMap resource_map =
1210 resource_provider_->GetChildToParentMap(child_id);
1211 ResourceProvider::ResourceId mapped_id1 = resource_map[id1];
1212 EXPECT_EQ(0u, mapped_id1);
1214 resource_provider_->DestroyChild(child_id);
1215 EXPECT_EQ(0u, resource_provider_->num_resources());
1217 ASSERT_EQ(1u, returned_to_child.size());
1218 EXPECT_FALSE(returned_to_child[0].lost);
1221 TEST_P(ResourceProviderTest, TransferInvalidSoftware) {
1222 if (GetParam() != ResourceProvider::Bitmap)
1223 return;
1225 gfx::Size size(1, 1);
1226 ResourceFormat format = RGBA_8888;
1227 size_t pixel_size = TextureSizeBytes(size, format);
1228 ASSERT_EQ(4U, pixel_size);
1230 ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource(
1231 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
1232 uint8_t data1[4] = { 1, 2, 3, 4 };
1233 gfx::Rect rect(size);
1234 child_resource_provider_->SetPixels(id1, data1, rect, rect, gfx::Vector2d());
1236 ReturnedResourceArray returned_to_child;
1237 int child_id =
1238 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1240 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1241 resource_ids_to_transfer.push_back(id1);
1242 TransferableResourceArray list;
1243 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1244 &list);
1245 ASSERT_EQ(1u, list.size());
1246 // Make invalid.
1247 list[0].mailbox_holder.mailbox.name[1] = 5;
1248 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1249 resource_provider_->ReceiveFromChild(child_id, list);
1252 EXPECT_EQ(1u, resource_provider_->num_resources());
1253 EXPECT_EQ(0u, returned_to_child.size());
1255 ResourceProvider::ResourceIdMap resource_map =
1256 resource_provider_->GetChildToParentMap(child_id);
1257 ResourceProvider::ResourceId mapped_id1 = resource_map[id1];
1258 EXPECT_NE(0u, mapped_id1);
1260 ResourceProvider::ScopedReadLockSoftware lock(resource_provider_.get(),
1261 mapped_id1);
1262 EXPECT_FALSE(lock.valid());
1265 resource_provider_->DestroyChild(child_id);
1266 EXPECT_EQ(0u, resource_provider_->num_resources());
1268 ASSERT_EQ(1u, returned_to_child.size());
1269 EXPECT_FALSE(returned_to_child[0].lost);
1272 TEST_P(ResourceProviderTest, DeleteExportedResources) {
1273 gfx::Size size(1, 1);
1274 ResourceFormat format = RGBA_8888;
1275 size_t pixel_size = TextureSizeBytes(size, format);
1276 ASSERT_EQ(4U, pixel_size);
1278 ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource(
1279 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
1280 uint8_t data1[4] = { 1, 2, 3, 4 };
1281 gfx::Rect rect(size);
1282 child_resource_provider_->SetPixels(id1, data1, rect, rect, gfx::Vector2d());
1284 ResourceProvider::ResourceId id2 = child_resource_provider_->CreateResource(
1285 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
1286 uint8_t data2[4] = {5, 5, 5, 5};
1287 child_resource_provider_->SetPixels(id2, data2, rect, rect, gfx::Vector2d());
1289 ReturnedResourceArray returned_to_child;
1290 int child_id =
1291 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1293 // Transfer some resources to the parent.
1294 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1295 resource_ids_to_transfer.push_back(id1);
1296 resource_ids_to_transfer.push_back(id2);
1297 TransferableResourceArray list;
1298 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1299 &list);
1300 ASSERT_EQ(2u, list.size());
1301 if (GetParam() == ResourceProvider::GLTexture) {
1302 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
1303 EXPECT_NE(0u, list[1].mailbox_holder.sync_point);
1305 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1306 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
1307 resource_provider_->ReceiveFromChild(child_id, list);
1308 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1309 resource_ids_to_transfer);
1312 EXPECT_EQ(2u, resource_provider_->num_resources());
1313 ResourceProvider::ResourceIdMap resource_map =
1314 resource_provider_->GetChildToParentMap(child_id);
1315 ResourceProvider::ResourceId mapped_id1 = resource_map[id1];
1316 ResourceProvider::ResourceId mapped_id2 = resource_map[id2];
1317 EXPECT_NE(0u, mapped_id1);
1318 EXPECT_NE(0u, mapped_id2);
1319 EXPECT_FALSE(resource_provider_->InUseByConsumer(id1));
1320 EXPECT_FALSE(resource_provider_->InUseByConsumer(id2));
1323 // The parent transfers the resources to the grandparent.
1324 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1325 resource_ids_to_transfer.push_back(mapped_id1);
1326 resource_ids_to_transfer.push_back(mapped_id2);
1327 TransferableResourceArray list;
1328 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
1330 ASSERT_EQ(2u, list.size());
1331 if (GetParam() == ResourceProvider::GLTexture) {
1332 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
1333 EXPECT_NE(0u, list[1].mailbox_holder.sync_point);
1335 EXPECT_TRUE(resource_provider_->InUseByConsumer(id1));
1336 EXPECT_TRUE(resource_provider_->InUseByConsumer(id2));
1338 // Release the resource in the parent. Set no resources as being in use. The
1339 // resources are exported so that can't be transferred back yet.
1340 ResourceProvider::ResourceIdArray no_resources;
1341 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
1343 EXPECT_EQ(0u, returned_to_child.size());
1344 EXPECT_EQ(2u, resource_provider_->num_resources());
1346 // Return the resources from the grandparent to the parent. They should be
1347 // returned to the child then.
1348 EXPECT_EQ(2u, list.size());
1349 EXPECT_EQ(mapped_id1, list[0].id);
1350 EXPECT_EQ(mapped_id2, list[1].id);
1351 ReturnedResourceArray returned;
1352 TransferableResource::ReturnResources(list, &returned);
1353 resource_provider_->ReceiveReturnsFromParent(returned);
1355 EXPECT_EQ(0u, resource_provider_->num_resources());
1356 ASSERT_EQ(2u, returned_to_child.size());
1357 if (GetParam() == ResourceProvider::GLTexture) {
1358 EXPECT_NE(0u, returned_to_child[0].sync_point);
1359 EXPECT_NE(0u, returned_to_child[1].sync_point);
1361 EXPECT_FALSE(returned_to_child[0].lost);
1362 EXPECT_FALSE(returned_to_child[1].lost);
1366 TEST_P(ResourceProviderTest, DestroyChildWithExportedResources) {
1367 gfx::Size size(1, 1);
1368 ResourceFormat format = RGBA_8888;
1369 size_t pixel_size = TextureSizeBytes(size, format);
1370 ASSERT_EQ(4U, pixel_size);
1372 ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource(
1373 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
1374 uint8_t data1[4] = {1, 2, 3, 4};
1375 gfx::Rect rect(size);
1376 child_resource_provider_->SetPixels(id1, data1, rect, rect, gfx::Vector2d());
1378 ResourceProvider::ResourceId id2 = child_resource_provider_->CreateResource(
1379 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
1380 uint8_t data2[4] = {5, 5, 5, 5};
1381 child_resource_provider_->SetPixels(id2, data2, rect, rect, gfx::Vector2d());
1383 ReturnedResourceArray returned_to_child;
1384 int child_id =
1385 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1387 // Transfer some resources to the parent.
1388 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1389 resource_ids_to_transfer.push_back(id1);
1390 resource_ids_to_transfer.push_back(id2);
1391 TransferableResourceArray list;
1392 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1393 &list);
1394 ASSERT_EQ(2u, list.size());
1395 if (GetParam() == ResourceProvider::GLTexture) {
1396 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
1397 EXPECT_NE(0u, list[1].mailbox_holder.sync_point);
1399 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1400 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
1401 resource_provider_->ReceiveFromChild(child_id, list);
1402 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1403 resource_ids_to_transfer);
1406 EXPECT_EQ(2u, resource_provider_->num_resources());
1407 ResourceProvider::ResourceIdMap resource_map =
1408 resource_provider_->GetChildToParentMap(child_id);
1409 ResourceProvider::ResourceId mapped_id1 = resource_map[id1];
1410 ResourceProvider::ResourceId mapped_id2 = resource_map[id2];
1411 EXPECT_NE(0u, mapped_id1);
1412 EXPECT_NE(0u, mapped_id2);
1413 EXPECT_FALSE(resource_provider_->InUseByConsumer(id1));
1414 EXPECT_FALSE(resource_provider_->InUseByConsumer(id2));
1417 // The parent transfers the resources to the grandparent.
1418 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1419 resource_ids_to_transfer.push_back(mapped_id1);
1420 resource_ids_to_transfer.push_back(mapped_id2);
1421 TransferableResourceArray list;
1422 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
1424 ASSERT_EQ(2u, list.size());
1425 if (GetParam() == ResourceProvider::GLTexture) {
1426 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
1427 EXPECT_NE(0u, list[1].mailbox_holder.sync_point);
1429 EXPECT_TRUE(resource_provider_->InUseByConsumer(id1));
1430 EXPECT_TRUE(resource_provider_->InUseByConsumer(id2));
1432 // Release the resource in the parent. Set no resources as being in use. The
1433 // resources are exported so that can't be transferred back yet.
1434 ResourceProvider::ResourceIdArray no_resources;
1435 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
1437 // Destroy the child, the resources should not be returned yet.
1438 EXPECT_EQ(0u, returned_to_child.size());
1439 EXPECT_EQ(2u, resource_provider_->num_resources());
1441 resource_provider_->DestroyChild(child_id);
1443 EXPECT_EQ(2u, resource_provider_->num_resources());
1444 ASSERT_EQ(0u, returned_to_child.size());
1446 // Return a resource from the grandparent, it should be returned at this
1447 // point.
1448 EXPECT_EQ(2u, list.size());
1449 EXPECT_EQ(mapped_id1, list[0].id);
1450 EXPECT_EQ(mapped_id2, list[1].id);
1451 TransferableResourceArray return_list;
1452 return_list.push_back(list[1]);
1453 list.pop_back();
1454 ReturnedResourceArray returned;
1455 TransferableResource::ReturnResources(return_list, &returned);
1456 resource_provider_->ReceiveReturnsFromParent(returned);
1458 EXPECT_EQ(1u, resource_provider_->num_resources());
1459 ASSERT_EQ(1u, returned_to_child.size());
1460 if (GetParam() == ResourceProvider::GLTexture) {
1461 EXPECT_NE(0u, returned_to_child[0].sync_point);
1463 EXPECT_FALSE(returned_to_child[0].lost);
1464 returned_to_child.clear();
1466 // Destroy the parent resource provider. The resource that's left should be
1467 // lost at this point, and returned.
1468 resource_provider_.reset();
1469 ASSERT_EQ(1u, returned_to_child.size());
1470 if (GetParam() == ResourceProvider::GLTexture) {
1471 EXPECT_NE(0u, returned_to_child[0].sync_point);
1473 EXPECT_TRUE(returned_to_child[0].lost);
1477 TEST_P(ResourceProviderTest, DeleteTransferredResources) {
1478 gfx::Size size(1, 1);
1479 ResourceFormat format = RGBA_8888;
1480 size_t pixel_size = TextureSizeBytes(size, format);
1481 ASSERT_EQ(4U, pixel_size);
1483 ResourceProvider::ResourceId id = child_resource_provider_->CreateResource(
1484 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
1485 uint8_t data[4] = { 1, 2, 3, 4 };
1486 gfx::Rect rect(size);
1487 child_resource_provider_->SetPixels(id, data, rect, rect, gfx::Vector2d());
1489 ReturnedResourceArray returned_to_child;
1490 int child_id =
1491 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1493 // Transfer some resource to the parent.
1494 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1495 resource_ids_to_transfer.push_back(id);
1496 TransferableResourceArray list;
1497 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1498 &list);
1499 ASSERT_EQ(1u, list.size());
1500 if (GetParam() == ResourceProvider::GLTexture)
1501 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
1502 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id));
1503 resource_provider_->ReceiveFromChild(child_id, list);
1504 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1505 resource_ids_to_transfer);
1508 // Delete textures in the child, while they are transfered.
1509 child_resource_provider_->DeleteResource(id);
1510 EXPECT_EQ(1u, child_resource_provider_->num_resources());
1512 EXPECT_EQ(0u, returned_to_child.size());
1514 // Transfer resources back from the parent to the child. Set no resources as
1515 // being in use.
1516 ResourceProvider::ResourceIdArray no_resources;
1517 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
1519 ASSERT_EQ(1u, returned_to_child.size());
1520 if (GetParam() == ResourceProvider::GLTexture)
1521 EXPECT_NE(0u, returned_to_child[0].sync_point);
1522 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
1524 EXPECT_EQ(0u, child_resource_provider_->num_resources());
1527 TEST_P(ResourceProviderTest, UnuseTransferredResources) {
1528 gfx::Size size(1, 1);
1529 ResourceFormat format = RGBA_8888;
1530 size_t pixel_size = TextureSizeBytes(size, format);
1531 ASSERT_EQ(4U, pixel_size);
1533 ResourceProvider::ResourceId id = child_resource_provider_->CreateResource(
1534 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
1535 uint8_t data[4] = {1, 2, 3, 4};
1536 gfx::Rect rect(size);
1537 child_resource_provider_->SetPixels(id, data, rect, rect, gfx::Vector2d());
1539 ReturnedResourceArray returned_to_child;
1540 int child_id =
1541 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1542 const ResourceProvider::ResourceIdMap& map =
1543 resource_provider_->GetChildToParentMap(child_id);
1545 // Transfer some resource to the parent.
1546 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1547 resource_ids_to_transfer.push_back(id);
1548 TransferableResourceArray list;
1549 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1550 &list);
1551 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id));
1552 resource_provider_->ReceiveFromChild(child_id, list);
1553 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1554 resource_ids_to_transfer);
1556 TransferableResourceArray sent_to_top_level;
1558 // Parent transfers to top-level.
1559 ASSERT_TRUE(map.find(id) != map.end());
1560 ResourceProvider::ResourceId parent_id = map.find(id)->second;
1561 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1562 resource_ids_to_transfer.push_back(parent_id);
1563 resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1564 &sent_to_top_level);
1565 EXPECT_TRUE(resource_provider_->InUseByConsumer(parent_id));
1568 // Stop using resource.
1569 ResourceProvider::ResourceIdArray empty;
1570 resource_provider_->DeclareUsedResourcesFromChild(child_id, empty);
1571 // Resource is not yet returned to the child, since it's in use by the
1572 // top-level.
1573 EXPECT_TRUE(returned_to_child.empty());
1576 // Send the resource to the parent again.
1577 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1578 resource_ids_to_transfer.push_back(id);
1579 TransferableResourceArray list;
1580 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1581 &list);
1582 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id));
1583 resource_provider_->ReceiveFromChild(child_id, list);
1584 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1585 resource_ids_to_transfer);
1588 // Receive returns back from top-level.
1589 ReturnedResourceArray returned;
1590 TransferableResource::ReturnResources(sent_to_top_level, &returned);
1591 resource_provider_->ReceiveReturnsFromParent(returned);
1592 // Resource is still not yet returned to the child, since it's declared used
1593 // in the parent.
1594 EXPECT_TRUE(returned_to_child.empty());
1595 ASSERT_TRUE(map.find(id) != map.end());
1596 ResourceProvider::ResourceId parent_id = map.find(id)->second;
1597 EXPECT_FALSE(resource_provider_->InUseByConsumer(parent_id));
1600 sent_to_top_level.clear();
1601 // Parent transfers again to top-level.
1602 ASSERT_TRUE(map.find(id) != map.end());
1603 ResourceProvider::ResourceId parent_id = map.find(id)->second;
1604 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1605 resource_ids_to_transfer.push_back(parent_id);
1606 resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1607 &sent_to_top_level);
1608 EXPECT_TRUE(resource_provider_->InUseByConsumer(parent_id));
1611 // Receive returns back from top-level.
1612 ReturnedResourceArray returned;
1613 TransferableResource::ReturnResources(sent_to_top_level, &returned);
1614 resource_provider_->ReceiveReturnsFromParent(returned);
1615 // Resource is still not yet returned to the child, since it's still
1616 // declared used in the parent.
1617 EXPECT_TRUE(returned_to_child.empty());
1618 ASSERT_TRUE(map.find(id) != map.end());
1619 ResourceProvider::ResourceId parent_id = map.find(id)->second;
1620 EXPECT_FALSE(resource_provider_->InUseByConsumer(parent_id));
1623 // Stop using resource.
1624 ResourceProvider::ResourceIdArray empty;
1625 resource_provider_->DeclareUsedResourcesFromChild(child_id, empty);
1626 // Resource should have been returned to the child, since it's no longer in
1627 // use by the top-level.
1628 ASSERT_EQ(1u, returned_to_child.size());
1629 EXPECT_EQ(id, returned_to_child[0].id);
1630 EXPECT_EQ(2, returned_to_child[0].count);
1631 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
1632 returned_to_child.clear();
1633 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id));
1637 class ResourceProviderTestTextureFilters : public ResourceProviderTest {
1638 public:
1639 static void RunTest(GLenum child_filter, GLenum parent_filter) {
1640 scoped_ptr<TextureStateTrackingContext> child_context_owned(
1641 new TextureStateTrackingContext);
1642 TextureStateTrackingContext* child_context = child_context_owned.get();
1644 FakeOutputSurfaceClient child_output_surface_client;
1645 scoped_ptr<OutputSurface> child_output_surface(FakeOutputSurface::Create3d(
1646 child_context_owned.PassAs<TestWebGraphicsContext3D>()));
1647 CHECK(child_output_surface->BindToClient(&child_output_surface_client));
1648 scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
1649 new TestSharedBitmapManager());
1651 scoped_ptr<ResourceProvider> child_resource_provider(
1652 ResourceProvider::Create(child_output_surface.get(),
1653 shared_bitmap_manager.get(),
1655 false,
1657 false));
1659 scoped_ptr<TextureStateTrackingContext> parent_context_owned(
1660 new TextureStateTrackingContext);
1661 TextureStateTrackingContext* parent_context = parent_context_owned.get();
1663 FakeOutputSurfaceClient parent_output_surface_client;
1664 scoped_ptr<OutputSurface> parent_output_surface(FakeOutputSurface::Create3d(
1665 parent_context_owned.PassAs<TestWebGraphicsContext3D>()));
1666 CHECK(parent_output_surface->BindToClient(&parent_output_surface_client));
1668 scoped_ptr<ResourceProvider> parent_resource_provider(
1669 ResourceProvider::Create(parent_output_surface.get(),
1670 shared_bitmap_manager.get(),
1672 false,
1674 false));
1676 gfx::Size size(1, 1);
1677 ResourceFormat format = RGBA_8888;
1678 int child_texture_id = 1;
1679 int parent_texture_id = 2;
1681 size_t pixel_size = TextureSizeBytes(size, format);
1682 ASSERT_EQ(4U, pixel_size);
1684 ResourceProvider::ResourceId id = child_resource_provider->CreateResource(
1685 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
1687 // The new texture is created with GL_LINEAR.
1688 EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, child_texture_id))
1689 .Times(2); // Once to create and once to allocate.
1690 EXPECT_CALL(*child_context,
1691 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
1692 EXPECT_CALL(*child_context,
1693 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
1694 EXPECT_CALL(
1695 *child_context,
1696 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
1697 EXPECT_CALL(
1698 *child_context,
1699 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
1700 EXPECT_CALL(*child_context,
1701 texParameteri(GL_TEXTURE_2D,
1702 GL_TEXTURE_POOL_CHROMIUM,
1703 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM));
1704 child_resource_provider->AllocateForTesting(id);
1705 Mock::VerifyAndClearExpectations(child_context);
1707 uint8_t data[4] = { 1, 2, 3, 4 };
1708 gfx::Rect rect(size);
1710 EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, child_texture_id));
1711 child_resource_provider->SetPixels(id, data, rect, rect, gfx::Vector2d());
1712 Mock::VerifyAndClearExpectations(child_context);
1714 // The texture is set to |child_filter| in the child.
1715 EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, child_texture_id));
1716 if (child_filter != GL_LINEAR) {
1717 EXPECT_CALL(
1718 *child_context,
1719 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, child_filter));
1720 EXPECT_CALL(
1721 *child_context,
1722 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, child_filter));
1724 SetResourceFilter(child_resource_provider.get(), id, child_filter);
1725 Mock::VerifyAndClearExpectations(child_context);
1727 ReturnedResourceArray returned_to_child;
1728 int child_id = parent_resource_provider->CreateChild(
1729 GetReturnCallback(&returned_to_child));
1731 // Transfer some resource to the parent.
1732 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1733 resource_ids_to_transfer.push_back(id);
1734 TransferableResourceArray list;
1736 EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, child_texture_id));
1737 EXPECT_CALL(*child_context,
1738 produceTextureCHROMIUM(GL_TEXTURE_2D, _));
1739 EXPECT_CALL(*child_context, insertSyncPoint());
1740 child_resource_provider->PrepareSendToParent(resource_ids_to_transfer,
1741 &list);
1742 Mock::VerifyAndClearExpectations(child_context);
1744 ASSERT_EQ(1u, list.size());
1745 EXPECT_EQ(static_cast<unsigned>(child_filter), list[0].filter);
1747 EXPECT_CALL(*parent_context,
1748 bindTexture(GL_TEXTURE_2D, parent_texture_id));
1749 EXPECT_CALL(*parent_context, consumeTextureCHROMIUM(GL_TEXTURE_2D, _));
1750 parent_resource_provider->ReceiveFromChild(child_id, list);
1752 parent_resource_provider->WaitSyncPointIfNeeded(list[0].id);
1753 ResourceProvider::ScopedReadLockGL lock(parent_resource_provider.get(),
1754 list[0].id);
1756 Mock::VerifyAndClearExpectations(parent_context);
1758 parent_resource_provider->DeclareUsedResourcesFromChild(
1759 child_id, resource_ids_to_transfer);
1760 Mock::VerifyAndClearExpectations(parent_context);
1762 ResourceProvider::ResourceIdMap resource_map =
1763 parent_resource_provider->GetChildToParentMap(child_id);
1764 ResourceProvider::ResourceId mapped_id = resource_map[id];
1765 EXPECT_NE(0u, mapped_id);
1767 // The texture is set to |parent_filter| in the parent.
1768 EXPECT_CALL(*parent_context, bindTexture(GL_TEXTURE_2D, parent_texture_id));
1769 EXPECT_CALL(
1770 *parent_context,
1771 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, parent_filter));
1772 EXPECT_CALL(
1773 *parent_context,
1774 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, parent_filter));
1775 SetResourceFilter(parent_resource_provider.get(), mapped_id, parent_filter);
1776 Mock::VerifyAndClearExpectations(parent_context);
1778 // The texture should be reset to |child_filter| in the parent when it is
1779 // returned, since that is how it was received.
1780 EXPECT_CALL(*parent_context, bindTexture(GL_TEXTURE_2D, parent_texture_id));
1781 EXPECT_CALL(
1782 *parent_context,
1783 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, child_filter));
1784 EXPECT_CALL(
1785 *parent_context,
1786 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, child_filter));
1789 EXPECT_EQ(0u, returned_to_child.size());
1791 // Transfer resources back from the parent to the child. Set no resources
1792 // as being in use.
1793 ResourceProvider::ResourceIdArray no_resources;
1794 EXPECT_CALL(*parent_context, insertSyncPoint());
1795 parent_resource_provider->DeclareUsedResourcesFromChild(child_id,
1796 no_resources);
1797 Mock::VerifyAndClearExpectations(parent_context);
1799 ASSERT_EQ(1u, returned_to_child.size());
1800 child_resource_provider->ReceiveReturnsFromParent(returned_to_child);
1803 // The child remembers the texture filter is set to |child_filter|.
1804 EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, child_texture_id));
1805 SetResourceFilter(child_resource_provider.get(), id, child_filter);
1806 Mock::VerifyAndClearExpectations(child_context);
1810 TEST_P(ResourceProviderTest, TextureFilters_ChildNearestParentLinear) {
1811 if (GetParam() != ResourceProvider::GLTexture)
1812 return;
1813 ResourceProviderTestTextureFilters::RunTest(GL_NEAREST, GL_LINEAR);
1816 TEST_P(ResourceProviderTest, TextureFilters_ChildLinearParentNearest) {
1817 if (GetParam() != ResourceProvider::GLTexture)
1818 return;
1819 ResourceProviderTestTextureFilters::RunTest(GL_LINEAR, GL_NEAREST);
1822 TEST_P(ResourceProviderTest, TransferMailboxResources) {
1823 // Other mailbox transfers tested elsewhere.
1824 if (GetParam() != ResourceProvider::GLTexture)
1825 return;
1826 unsigned texture = context()->createTexture();
1827 context()->bindTexture(GL_TEXTURE_2D, texture);
1828 uint8_t data[4] = { 1, 2, 3, 4 };
1829 context()->texImage2D(
1830 GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &data);
1831 gpu::Mailbox mailbox;
1832 context()->genMailboxCHROMIUM(mailbox.name);
1833 context()->produceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
1834 uint32 sync_point = context()->insertSyncPoint();
1836 // All the logic below assumes that the sync points are all positive.
1837 EXPECT_LT(0u, sync_point);
1839 uint32 release_sync_point = 0;
1840 bool lost_resource = false;
1841 ReleaseCallback callback =
1842 base::Bind(ReleaseTextureMailbox, &release_sync_point, &lost_resource);
1843 ResourceProvider::ResourceId resource =
1844 resource_provider_->CreateResourceFromTextureMailbox(
1845 TextureMailbox(mailbox, GL_TEXTURE_2D, sync_point),
1846 SingleReleaseCallback::Create(callback));
1847 EXPECT_EQ(1u, context()->NumTextures());
1848 EXPECT_EQ(0u, release_sync_point);
1850 // Transfer the resource, expect the sync points to be consistent.
1851 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1852 resource_ids_to_transfer.push_back(resource);
1853 TransferableResourceArray list;
1854 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
1855 ASSERT_EQ(1u, list.size());
1856 EXPECT_LE(sync_point, list[0].mailbox_holder.sync_point);
1857 EXPECT_EQ(0,
1858 memcmp(mailbox.name,
1859 list[0].mailbox_holder.mailbox.name,
1860 sizeof(mailbox.name)));
1861 EXPECT_EQ(0u, release_sync_point);
1863 context()->waitSyncPoint(list[0].mailbox_holder.sync_point);
1864 unsigned other_texture = context()->createTexture();
1865 context()->bindTexture(GL_TEXTURE_2D, other_texture);
1866 context()->consumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
1867 uint8_t test_data[4] = { 0 };
1868 context()->GetPixels(
1869 gfx::Size(1, 1), RGBA_8888, test_data);
1870 EXPECT_EQ(0, memcmp(data, test_data, sizeof(data)));
1871 context()->produceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
1872 context()->deleteTexture(other_texture);
1873 list[0].mailbox_holder.sync_point = context()->insertSyncPoint();
1874 EXPECT_LT(0u, list[0].mailbox_holder.sync_point);
1876 // Receive the resource, then delete it, expect the sync points to be
1877 // consistent.
1878 ReturnedResourceArray returned;
1879 TransferableResource::ReturnResources(list, &returned);
1880 resource_provider_->ReceiveReturnsFromParent(returned);
1881 EXPECT_EQ(1u, context()->NumTextures());
1882 EXPECT_EQ(0u, release_sync_point);
1884 resource_provider_->DeleteResource(resource);
1885 EXPECT_LE(list[0].mailbox_holder.sync_point, release_sync_point);
1886 EXPECT_FALSE(lost_resource);
1889 // We're going to do the same thing as above, but testing the case where we
1890 // delete the resource before we receive it back.
1891 sync_point = release_sync_point;
1892 EXPECT_LT(0u, sync_point);
1893 release_sync_point = 0;
1894 resource = resource_provider_->CreateResourceFromTextureMailbox(
1895 TextureMailbox(mailbox, GL_TEXTURE_2D, sync_point),
1896 SingleReleaseCallback::Create(callback));
1897 EXPECT_EQ(1u, context()->NumTextures());
1898 EXPECT_EQ(0u, release_sync_point);
1900 // Transfer the resource, expect the sync points to be consistent.
1901 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1902 resource_ids_to_transfer.push_back(resource);
1903 TransferableResourceArray list;
1904 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
1905 ASSERT_EQ(1u, list.size());
1906 EXPECT_LE(sync_point, list[0].mailbox_holder.sync_point);
1907 EXPECT_EQ(0,
1908 memcmp(mailbox.name,
1909 list[0].mailbox_holder.mailbox.name,
1910 sizeof(mailbox.name)));
1911 EXPECT_EQ(0u, release_sync_point);
1913 context()->waitSyncPoint(list[0].mailbox_holder.sync_point);
1914 unsigned other_texture = context()->createTexture();
1915 context()->bindTexture(GL_TEXTURE_2D, other_texture);
1916 context()->consumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
1917 uint8_t test_data[4] = { 0 };
1918 context()->GetPixels(
1919 gfx::Size(1, 1), RGBA_8888, test_data);
1920 EXPECT_EQ(0, memcmp(data, test_data, sizeof(data)));
1921 context()->produceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
1922 context()->deleteTexture(other_texture);
1923 list[0].mailbox_holder.sync_point = context()->insertSyncPoint();
1924 EXPECT_LT(0u, list[0].mailbox_holder.sync_point);
1926 // Delete the resource, which shouldn't do anything.
1927 resource_provider_->DeleteResource(resource);
1928 EXPECT_EQ(1u, context()->NumTextures());
1929 EXPECT_EQ(0u, release_sync_point);
1931 // Then receive the resource which should release the mailbox, expect the
1932 // sync points to be consistent.
1933 ReturnedResourceArray returned;
1934 TransferableResource::ReturnResources(list, &returned);
1935 resource_provider_->ReceiveReturnsFromParent(returned);
1936 EXPECT_LE(list[0].mailbox_holder.sync_point, release_sync_point);
1937 EXPECT_FALSE(lost_resource);
1940 context()->waitSyncPoint(release_sync_point);
1941 context()->bindTexture(GL_TEXTURE_2D, texture);
1942 context()->consumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
1943 context()->deleteTexture(texture);
1946 TEST_P(ResourceProviderTest, LostResourceInParent) {
1947 gfx::Size size(1, 1);
1948 ResourceFormat format = RGBA_8888;
1949 ResourceProvider::ResourceId resource =
1950 child_resource_provider_->CreateResource(
1951 size,
1952 GL_CLAMP_TO_EDGE,
1953 ResourceProvider::TextureHintImmutable,
1954 format);
1955 child_resource_provider_->AllocateForTesting(resource);
1956 // Expect a GL resource to be lost.
1957 bool should_lose_resource = GetParam() == ResourceProvider::GLTexture;
1959 ReturnedResourceArray returned_to_child;
1960 int child_id =
1961 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1963 // Transfer the resource to the parent.
1964 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1965 resource_ids_to_transfer.push_back(resource);
1966 TransferableResourceArray list;
1967 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1968 &list);
1969 EXPECT_EQ(1u, list.size());
1971 resource_provider_->ReceiveFromChild(child_id, list);
1972 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1973 resource_ids_to_transfer);
1976 // Lose the output surface in the parent.
1977 resource_provider_->DidLoseOutputSurface();
1980 EXPECT_EQ(0u, returned_to_child.size());
1982 // Transfer resources back from the parent to the child. Set no resources as
1983 // being in use.
1984 ResourceProvider::ResourceIdArray no_resources;
1985 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
1987 // Expect a GL resource to be lost.
1988 ASSERT_EQ(1u, returned_to_child.size());
1989 EXPECT_EQ(should_lose_resource, returned_to_child[0].lost);
1990 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
1991 returned_to_child.clear();
1994 // A GL resource should be lost.
1995 EXPECT_EQ(should_lose_resource, child_resource_provider_->IsLost(resource));
1997 // Lost resources stay in use in the parent forever.
1998 EXPECT_EQ(should_lose_resource,
1999 child_resource_provider_->InUseByConsumer(resource));
2002 TEST_P(ResourceProviderTest, LostResourceInGrandParent) {
2003 gfx::Size size(1, 1);
2004 ResourceFormat format = RGBA_8888;
2005 ResourceProvider::ResourceId resource =
2006 child_resource_provider_->CreateResource(
2007 size,
2008 GL_CLAMP_TO_EDGE,
2009 ResourceProvider::TextureHintImmutable,
2010 format);
2011 child_resource_provider_->AllocateForTesting(resource);
2013 ReturnedResourceArray returned_to_child;
2014 int child_id =
2015 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
2017 // Transfer the resource to the parent.
2018 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2019 resource_ids_to_transfer.push_back(resource);
2020 TransferableResourceArray list;
2021 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
2022 &list);
2023 EXPECT_EQ(1u, list.size());
2025 resource_provider_->ReceiveFromChild(child_id, list);
2026 resource_provider_->DeclareUsedResourcesFromChild(child_id,
2027 resource_ids_to_transfer);
2031 ResourceProvider::ResourceIdMap resource_map =
2032 resource_provider_->GetChildToParentMap(child_id);
2033 ResourceProvider::ResourceId parent_resource = resource_map[resource];
2034 EXPECT_NE(0u, parent_resource);
2036 // Transfer to a grandparent.
2037 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2038 resource_ids_to_transfer.push_back(parent_resource);
2039 TransferableResourceArray list;
2040 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
2042 // Receive back a lost resource from the grandparent.
2043 EXPECT_EQ(1u, list.size());
2044 EXPECT_EQ(parent_resource, list[0].id);
2045 ReturnedResourceArray returned;
2046 TransferableResource::ReturnResources(list, &returned);
2047 EXPECT_EQ(1u, returned.size());
2048 EXPECT_EQ(parent_resource, returned[0].id);
2049 returned[0].lost = true;
2050 resource_provider_->ReceiveReturnsFromParent(returned);
2052 // The resource should be lost.
2053 EXPECT_TRUE(resource_provider_->IsLost(parent_resource));
2055 // Lost resources stay in use in the parent forever.
2056 EXPECT_TRUE(resource_provider_->InUseByConsumer(parent_resource));
2060 EXPECT_EQ(0u, returned_to_child.size());
2062 // Transfer resources back from the parent to the child. Set no resources as
2063 // being in use.
2064 ResourceProvider::ResourceIdArray no_resources;
2065 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
2067 // Expect the resource to be lost.
2068 ASSERT_EQ(1u, returned_to_child.size());
2069 EXPECT_TRUE(returned_to_child[0].lost);
2070 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
2071 returned_to_child.clear();
2074 // The resource should be lost.
2075 EXPECT_TRUE(child_resource_provider_->IsLost(resource));
2077 // Lost resources stay in use in the parent forever.
2078 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(resource));
2081 TEST_P(ResourceProviderTest, LostMailboxInParent) {
2082 uint32 release_sync_point = 0;
2083 bool lost_resource = false;
2084 bool release_called = false;
2085 uint32 sync_point = 0;
2086 ResourceProvider::ResourceId resource = CreateChildMailbox(
2087 &release_sync_point, &lost_resource, &release_called, &sync_point);
2089 ReturnedResourceArray returned_to_child;
2090 int child_id =
2091 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
2093 // Transfer the resource to the parent.
2094 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2095 resource_ids_to_transfer.push_back(resource);
2096 TransferableResourceArray list;
2097 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
2098 &list);
2099 EXPECT_EQ(1u, list.size());
2101 resource_provider_->ReceiveFromChild(child_id, list);
2102 resource_provider_->DeclareUsedResourcesFromChild(child_id,
2103 resource_ids_to_transfer);
2106 // Lose the output surface in the parent.
2107 resource_provider_->DidLoseOutputSurface();
2110 EXPECT_EQ(0u, returned_to_child.size());
2112 // Transfer resources back from the parent to the child. Set no resources as
2113 // being in use.
2114 ResourceProvider::ResourceIdArray no_resources;
2115 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
2117 ASSERT_EQ(1u, returned_to_child.size());
2118 // Losing an output surface only loses hardware resources.
2119 EXPECT_EQ(returned_to_child[0].lost,
2120 GetParam() == ResourceProvider::GLTexture);
2121 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
2122 returned_to_child.clear();
2125 // Delete the resource in the child. Expect the resource to be lost if it's
2126 // a GL texture.
2127 child_resource_provider_->DeleteResource(resource);
2128 EXPECT_EQ(lost_resource, GetParam() == ResourceProvider::GLTexture);
2131 TEST_P(ResourceProviderTest, LostMailboxInGrandParent) {
2132 uint32 release_sync_point = 0;
2133 bool lost_resource = false;
2134 bool release_called = false;
2135 uint32 sync_point = 0;
2136 ResourceProvider::ResourceId resource = CreateChildMailbox(
2137 &release_sync_point, &lost_resource, &release_called, &sync_point);
2139 ReturnedResourceArray returned_to_child;
2140 int child_id =
2141 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
2143 // Transfer the resource to the parent.
2144 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2145 resource_ids_to_transfer.push_back(resource);
2146 TransferableResourceArray list;
2147 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
2148 &list);
2149 EXPECT_EQ(1u, list.size());
2151 resource_provider_->ReceiveFromChild(child_id, list);
2152 resource_provider_->DeclareUsedResourcesFromChild(child_id,
2153 resource_ids_to_transfer);
2157 ResourceProvider::ResourceIdMap resource_map =
2158 resource_provider_->GetChildToParentMap(child_id);
2159 ResourceProvider::ResourceId parent_resource = resource_map[resource];
2160 EXPECT_NE(0u, parent_resource);
2162 // Transfer to a grandparent.
2163 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2164 resource_ids_to_transfer.push_back(parent_resource);
2165 TransferableResourceArray list;
2166 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
2168 // Receive back a lost resource from the grandparent.
2169 EXPECT_EQ(1u, list.size());
2170 EXPECT_EQ(parent_resource, list[0].id);
2171 ReturnedResourceArray returned;
2172 TransferableResource::ReturnResources(list, &returned);
2173 EXPECT_EQ(1u, returned.size());
2174 EXPECT_EQ(parent_resource, returned[0].id);
2175 returned[0].lost = true;
2176 resource_provider_->ReceiveReturnsFromParent(returned);
2180 EXPECT_EQ(0u, returned_to_child.size());
2182 // Transfer resources back from the parent to the child. Set no resources as
2183 // being in use.
2184 ResourceProvider::ResourceIdArray no_resources;
2185 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
2187 // Expect the resource to be lost.
2188 ASSERT_EQ(1u, returned_to_child.size());
2189 EXPECT_TRUE(returned_to_child[0].lost);
2190 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
2191 returned_to_child.clear();
2194 // Delete the resource in the child. Expect the resource to be lost.
2195 child_resource_provider_->DeleteResource(resource);
2196 EXPECT_TRUE(lost_resource);
2199 TEST_P(ResourceProviderTest, Shutdown) {
2200 uint32 release_sync_point = 0;
2201 bool lost_resource = false;
2202 bool release_called = false;
2203 uint32 sync_point = 0;
2204 CreateChildMailbox(
2205 &release_sync_point, &lost_resource, &release_called, &sync_point);
2207 EXPECT_EQ(0u, release_sync_point);
2208 EXPECT_FALSE(lost_resource);
2210 child_resource_provider_.reset();
2212 if (GetParam() == ResourceProvider::GLTexture) {
2213 EXPECT_LE(sync_point, release_sync_point);
2215 EXPECT_TRUE(release_called);
2216 EXPECT_FALSE(lost_resource);
2219 TEST_P(ResourceProviderTest, ShutdownWithExportedResource) {
2220 uint32 release_sync_point = 0;
2221 bool lost_resource = false;
2222 bool release_called = false;
2223 uint32 sync_point = 0;
2224 ResourceProvider::ResourceId resource = CreateChildMailbox(
2225 &release_sync_point, &lost_resource, &release_called, &sync_point);
2227 // Transfer the resource, so we can't release it properly on shutdown.
2228 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2229 resource_ids_to_transfer.push_back(resource);
2230 TransferableResourceArray list;
2231 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
2232 &list);
2234 EXPECT_EQ(0u, release_sync_point);
2235 EXPECT_FALSE(lost_resource);
2237 child_resource_provider_.reset();
2239 // Since the resource is in the parent, the child considers it lost.
2240 EXPECT_EQ(0u, release_sync_point);
2241 EXPECT_TRUE(lost_resource);
2244 TEST_P(ResourceProviderTest, LostContext) {
2245 // TextureMailbox callbacks only exist for GL textures for now.
2246 if (GetParam() != ResourceProvider::GLTexture)
2247 return;
2248 unsigned texture = context()->createTexture();
2249 context()->bindTexture(GL_TEXTURE_2D, texture);
2250 gpu::Mailbox mailbox;
2251 context()->genMailboxCHROMIUM(mailbox.name);
2252 context()->produceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
2253 uint32 sync_point = context()->insertSyncPoint();
2255 EXPECT_LT(0u, sync_point);
2257 uint32 release_sync_point = 0;
2258 bool lost_resource = false;
2259 scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create(
2260 base::Bind(ReleaseTextureMailbox, &release_sync_point, &lost_resource));
2261 resource_provider_->CreateResourceFromTextureMailbox(
2262 TextureMailbox(mailbox, GL_TEXTURE_2D, sync_point), callback.Pass());
2264 EXPECT_EQ(0u, release_sync_point);
2265 EXPECT_FALSE(lost_resource);
2267 resource_provider_->DidLoseOutputSurface();
2268 resource_provider_.reset();
2270 EXPECT_LE(sync_point, release_sync_point);
2271 EXPECT_TRUE(lost_resource);
2274 TEST_P(ResourceProviderTest, ScopedSampler) {
2275 // Sampling is only supported for GL textures.
2276 if (GetParam() != ResourceProvider::GLTexture)
2277 return;
2279 scoped_ptr<TextureStateTrackingContext> context_owned(
2280 new TextureStateTrackingContext);
2281 TextureStateTrackingContext* context = context_owned.get();
2283 FakeOutputSurfaceClient output_surface_client;
2284 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
2285 context_owned.PassAs<TestWebGraphicsContext3D>()));
2286 CHECK(output_surface->BindToClient(&output_surface_client));
2288 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
2289 output_surface.get(), shared_bitmap_manager_.get(), 0, false, 1, false));
2291 gfx::Size size(1, 1);
2292 ResourceFormat format = RGBA_8888;
2293 int texture_id = 1;
2295 ResourceProvider::ResourceId id = resource_provider->CreateResource(
2296 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
2298 // Check that the texture gets created with the right sampler settings.
2299 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id))
2300 .Times(2); // Once to create and once to allocate.
2301 EXPECT_CALL(*context,
2302 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
2303 EXPECT_CALL(*context,
2304 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
2305 EXPECT_CALL(
2306 *context,
2307 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
2308 EXPECT_CALL(
2309 *context,
2310 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
2311 EXPECT_CALL(*context,
2312 texParameteri(GL_TEXTURE_2D,
2313 GL_TEXTURE_POOL_CHROMIUM,
2314 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM));
2316 resource_provider->AllocateForTesting(id);
2317 Mock::VerifyAndClearExpectations(context);
2319 // Creating a sampler with the default filter should not change any texture
2320 // parameters.
2322 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
2323 ResourceProvider::ScopedSamplerGL sampler(
2324 resource_provider.get(), id, GL_TEXTURE_2D, GL_LINEAR);
2325 Mock::VerifyAndClearExpectations(context);
2328 // Using a different filter should be reflected in the texture parameters.
2330 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
2331 EXPECT_CALL(
2332 *context,
2333 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
2334 EXPECT_CALL(
2335 *context,
2336 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
2337 ResourceProvider::ScopedSamplerGL sampler(
2338 resource_provider.get(), id, GL_TEXTURE_2D, GL_NEAREST);
2339 Mock::VerifyAndClearExpectations(context);
2342 // Test resetting to the default filter.
2344 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
2345 EXPECT_CALL(*context,
2346 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
2347 EXPECT_CALL(*context,
2348 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
2349 ResourceProvider::ScopedSamplerGL sampler(
2350 resource_provider.get(), id, GL_TEXTURE_2D, GL_LINEAR);
2351 Mock::VerifyAndClearExpectations(context);
2355 TEST_P(ResourceProviderTest, ManagedResource) {
2356 // Sampling is only supported for GL textures.
2357 if (GetParam() != ResourceProvider::GLTexture)
2358 return;
2360 scoped_ptr<TextureStateTrackingContext> context_owned(
2361 new TextureStateTrackingContext);
2362 TextureStateTrackingContext* context = context_owned.get();
2364 FakeOutputSurfaceClient output_surface_client;
2365 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
2366 context_owned.PassAs<TestWebGraphicsContext3D>()));
2367 CHECK(output_surface->BindToClient(&output_surface_client));
2369 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
2370 output_surface.get(), shared_bitmap_manager_.get(), 0, false, 1, false));
2372 gfx::Size size(1, 1);
2373 ResourceFormat format = RGBA_8888;
2374 int texture_id = 1;
2376 // Check that the texture gets created with the right sampler settings.
2377 ResourceProvider::ResourceId id = resource_provider->CreateManagedResource(
2378 size,
2379 GL_TEXTURE_2D,
2380 GL_CLAMP_TO_EDGE,
2381 ResourceProvider::TextureHintImmutable,
2382 format);
2383 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
2384 EXPECT_CALL(*context,
2385 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
2386 EXPECT_CALL(*context,
2387 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
2388 EXPECT_CALL(
2389 *context,
2390 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
2391 EXPECT_CALL(
2392 *context,
2393 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
2394 EXPECT_CALL(*context,
2395 texParameteri(GL_TEXTURE_2D,
2396 GL_TEXTURE_POOL_CHROMIUM,
2397 GL_TEXTURE_POOL_MANAGED_CHROMIUM));
2398 resource_provider->CreateForTesting(id);
2399 EXPECT_NE(0u, id);
2401 Mock::VerifyAndClearExpectations(context);
2404 TEST_P(ResourceProviderTest, TextureWrapMode) {
2405 // Sampling is only supported for GL textures.
2406 if (GetParam() != ResourceProvider::GLTexture)
2407 return;
2409 scoped_ptr<TextureStateTrackingContext> context_owned(
2410 new TextureStateTrackingContext);
2411 TextureStateTrackingContext* context = context_owned.get();
2413 FakeOutputSurfaceClient output_surface_client;
2414 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
2415 context_owned.PassAs<TestWebGraphicsContext3D>()));
2416 CHECK(output_surface->BindToClient(&output_surface_client));
2418 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
2419 output_surface.get(), shared_bitmap_manager_.get(), 0, false, 1, false));
2421 gfx::Size size(1, 1);
2422 ResourceFormat format = RGBA_8888;
2423 GLenum texture_pool = GL_TEXTURE_POOL_UNMANAGED_CHROMIUM;
2425 for (int texture_id = 1; texture_id <= 2; ++texture_id) {
2426 GLint wrap_mode = texture_id == 1 ? GL_CLAMP_TO_EDGE : GL_REPEAT;
2427 // Check that the texture gets created with the right sampler settings.
2428 ResourceProvider::ResourceId id = resource_provider->CreateGLTexture(
2429 size,
2430 GL_TEXTURE_2D,
2431 texture_pool,
2432 wrap_mode,
2433 ResourceProvider::TextureHintImmutable,
2434 format);
2435 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
2436 EXPECT_CALL(*context,
2437 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
2438 EXPECT_CALL(*context,
2439 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
2440 EXPECT_CALL(*context,
2441 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap_mode));
2442 EXPECT_CALL(*context,
2443 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap_mode));
2444 EXPECT_CALL(*context,
2445 texParameteri(GL_TEXTURE_2D,
2446 GL_TEXTURE_POOL_CHROMIUM,
2447 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM));
2448 resource_provider->CreateForTesting(id);
2449 EXPECT_NE(0u, id);
2451 Mock::VerifyAndClearExpectations(context);
2455 TEST_P(ResourceProviderTest, TextureHint) {
2456 // Sampling is only supported for GL textures.
2457 if (GetParam() != ResourceProvider::GLTexture)
2458 return;
2460 scoped_ptr<TextureStateTrackingContext> context_owned(
2461 new TextureStateTrackingContext);
2462 TextureStateTrackingContext* context = context_owned.get();
2463 context->set_support_texture_storage(true);
2464 context->set_support_texture_usage(true);
2466 FakeOutputSurfaceClient output_surface_client;
2467 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
2468 context_owned.PassAs<TestWebGraphicsContext3D>()));
2469 CHECK(output_surface->BindToClient(&output_surface_client));
2471 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
2472 output_surface.get(), shared_bitmap_manager_.get(), 0, false, 1, false));
2474 gfx::Size size(1, 1);
2475 ResourceFormat format = RGBA_8888;
2476 GLenum texture_pool = GL_TEXTURE_POOL_UNMANAGED_CHROMIUM;
2478 const ResourceProvider::TextureHint hints[4] = {
2479 ResourceProvider::TextureHintDefault,
2480 ResourceProvider::TextureHintImmutable,
2481 ResourceProvider::TextureHintFramebuffer,
2482 ResourceProvider::TextureHintImmutableFramebuffer,
2484 for (GLuint texture_id = 1; texture_id <= arraysize(hints); ++texture_id) {
2485 // Check that the texture gets created with the right sampler settings.
2486 ResourceProvider::ResourceId id =
2487 resource_provider->CreateGLTexture(size,
2488 GL_TEXTURE_2D,
2489 texture_pool,
2490 GL_CLAMP_TO_EDGE,
2491 hints[texture_id - 1],
2492 format);
2493 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
2494 EXPECT_CALL(*context,
2495 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
2496 EXPECT_CALL(*context,
2497 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
2498 EXPECT_CALL(
2499 *context,
2500 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
2501 EXPECT_CALL(
2502 *context,
2503 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
2504 EXPECT_CALL(*context,
2505 texParameteri(GL_TEXTURE_2D,
2506 GL_TEXTURE_POOL_CHROMIUM,
2507 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM));
2508 // Check only TextureHintFramebuffer set GL_TEXTURE_USAGE_ANGLE.
2509 bool is_framebuffer_hint =
2510 hints[texture_id - 1] & ResourceProvider::TextureHintFramebuffer;
2511 EXPECT_CALL(*context,
2512 texParameteri(GL_TEXTURE_2D,
2513 GL_TEXTURE_USAGE_ANGLE,
2514 GL_FRAMEBUFFER_ATTACHMENT_ANGLE))
2515 .Times(is_framebuffer_hint ? 1 : 0);
2516 resource_provider->CreateForTesting(id);
2517 EXPECT_NE(0u, id);
2519 Mock::VerifyAndClearExpectations(context);
2523 TEST_P(ResourceProviderTest, TextureMailbox_SharedMemory) {
2524 if (GetParam() != ResourceProvider::Bitmap)
2525 return;
2527 gfx::Size size(64, 64);
2528 const uint32_t kBadBeef = 0xbadbeef;
2529 scoped_ptr<base::SharedMemory> shared_memory(
2530 CreateAndFillSharedMemory(size, kBadBeef));
2532 FakeOutputSurfaceClient output_surface_client;
2533 scoped_ptr<OutputSurface> output_surface(
2534 FakeOutputSurface::CreateSoftware(make_scoped_ptr(
2535 new SoftwareOutputDevice)));
2536 CHECK(output_surface->BindToClient(&output_surface_client));
2538 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
2539 output_surface.get(), shared_bitmap_manager_.get(), 0, false, 1, false));
2541 scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create(
2542 base::Bind(&EmptyReleaseCallback));
2543 TextureMailbox mailbox(shared_memory.get(), size);
2545 ResourceProvider::ResourceId id =
2546 resource_provider->CreateResourceFromTextureMailbox(
2547 mailbox, callback.Pass());
2548 EXPECT_NE(0u, id);
2551 ResourceProvider::ScopedReadLockSoftware lock(resource_provider.get(), id);
2552 const SkBitmap* sk_bitmap = lock.sk_bitmap();
2553 EXPECT_EQ(sk_bitmap->width(), size.width());
2554 EXPECT_EQ(sk_bitmap->height(), size.height());
2555 EXPECT_EQ(*sk_bitmap->getAddr32(16, 16), kBadBeef);
2559 TEST_P(ResourceProviderTest, TextureMailbox_GLTexture2D) {
2560 // Mailboxing is only supported for GL textures.
2561 if (GetParam() != ResourceProvider::GLTexture)
2562 return;
2564 scoped_ptr<TextureStateTrackingContext> context_owned(
2565 new TextureStateTrackingContext);
2566 TextureStateTrackingContext* context = context_owned.get();
2568 FakeOutputSurfaceClient output_surface_client;
2569 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
2570 context_owned.PassAs<TestWebGraphicsContext3D>()));
2571 CHECK(output_surface->BindToClient(&output_surface_client));
2573 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
2574 output_surface.get(), shared_bitmap_manager_.get(), 0, false, 1, false));
2576 unsigned texture_id = 1;
2577 uint32 sync_point = 30;
2578 unsigned target = GL_TEXTURE_2D;
2580 EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
2581 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
2582 EXPECT_CALL(*context, insertSyncPoint()).Times(0);
2583 EXPECT_CALL(*context, produceTextureCHROMIUM(_, _)).Times(0);
2584 EXPECT_CALL(*context, consumeTextureCHROMIUM(_, _)).Times(0);
2586 gpu::Mailbox gpu_mailbox;
2587 memcpy(gpu_mailbox.name, "Hello world", strlen("Hello world") + 1);
2588 scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create(
2589 base::Bind(&EmptyReleaseCallback));
2591 TextureMailbox mailbox(gpu_mailbox, target, sync_point);
2593 ResourceProvider::ResourceId id =
2594 resource_provider->CreateResourceFromTextureMailbox(
2595 mailbox, callback.Pass());
2596 EXPECT_NE(0u, id);
2598 Mock::VerifyAndClearExpectations(context);
2601 // Mailbox sync point WaitSyncPoint before using the texture.
2602 EXPECT_CALL(*context, waitSyncPoint(sync_point));
2603 resource_provider->WaitSyncPointIfNeeded(id);
2604 Mock::VerifyAndClearExpectations(context);
2606 // Using the texture does a consume of the mailbox.
2607 EXPECT_CALL(*context, bindTexture(target, texture_id));
2608 EXPECT_CALL(*context, consumeTextureCHROMIUM(target, _));
2610 EXPECT_CALL(*context, insertSyncPoint()).Times(0);
2611 EXPECT_CALL(*context, produceTextureCHROMIUM(_, _)).Times(0);
2613 ResourceProvider::ScopedReadLockGL lock(resource_provider.get(), id);
2614 Mock::VerifyAndClearExpectations(context);
2616 // When done with it, a sync point should be inserted, but no produce is
2617 // necessary.
2618 EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
2619 EXPECT_CALL(*context, insertSyncPoint());
2620 EXPECT_CALL(*context, produceTextureCHROMIUM(_, _)).Times(0);
2622 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
2623 EXPECT_CALL(*context, consumeTextureCHROMIUM(_, _)).Times(0);
2627 TEST_P(ResourceProviderTest, TextureMailbox_GLTextureExternalOES) {
2628 // Mailboxing is only supported for GL textures.
2629 if (GetParam() != ResourceProvider::GLTexture)
2630 return;
2632 scoped_ptr<TextureStateTrackingContext> context_owned(
2633 new TextureStateTrackingContext);
2634 TextureStateTrackingContext* context = context_owned.get();
2636 FakeOutputSurfaceClient output_surface_client;
2637 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
2638 context_owned.PassAs<TestWebGraphicsContext3D>()));
2639 CHECK(output_surface->BindToClient(&output_surface_client));
2641 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
2642 output_surface.get(), shared_bitmap_manager_.get(), 0, false, 1, false));
2644 unsigned texture_id = 1;
2645 uint32 sync_point = 30;
2646 unsigned target = GL_TEXTURE_EXTERNAL_OES;
2648 EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
2649 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
2650 EXPECT_CALL(*context, insertSyncPoint()).Times(0);
2651 EXPECT_CALL(*context, produceTextureCHROMIUM(_, _)).Times(0);
2652 EXPECT_CALL(*context, consumeTextureCHROMIUM(_, _)).Times(0);
2654 gpu::Mailbox gpu_mailbox;
2655 memcpy(gpu_mailbox.name, "Hello world", strlen("Hello world") + 1);
2656 scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create(
2657 base::Bind(&EmptyReleaseCallback));
2659 TextureMailbox mailbox(gpu_mailbox, target, sync_point);
2661 ResourceProvider::ResourceId id =
2662 resource_provider->CreateResourceFromTextureMailbox(
2663 mailbox, callback.Pass());
2664 EXPECT_NE(0u, id);
2666 Mock::VerifyAndClearExpectations(context);
2669 // Mailbox sync point WaitSyncPoint before using the texture.
2670 EXPECT_CALL(*context, waitSyncPoint(sync_point));
2671 resource_provider->WaitSyncPointIfNeeded(id);
2672 Mock::VerifyAndClearExpectations(context);
2674 // Using the texture does a consume of the mailbox.
2675 EXPECT_CALL(*context, bindTexture(target, texture_id));
2676 EXPECT_CALL(*context, consumeTextureCHROMIUM(target, _));
2678 EXPECT_CALL(*context, insertSyncPoint()).Times(0);
2679 EXPECT_CALL(*context, produceTextureCHROMIUM(_, _)).Times(0);
2681 ResourceProvider::ScopedReadLockGL lock(resource_provider.get(), id);
2682 Mock::VerifyAndClearExpectations(context);
2684 // When done with it, a sync point should be inserted, but no produce is
2685 // necessary.
2686 EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
2687 EXPECT_CALL(*context, insertSyncPoint());
2688 EXPECT_CALL(*context, produceTextureCHROMIUM(_, _)).Times(0);
2690 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
2691 EXPECT_CALL(*context, consumeTextureCHROMIUM(_, _)).Times(0);
2695 TEST_P(ResourceProviderTest,
2696 TextureMailbox_WaitSyncPointIfNeeded_WithSyncPoint) {
2697 // Mailboxing is only supported for GL textures.
2698 if (GetParam() != ResourceProvider::GLTexture)
2699 return;
2701 scoped_ptr<TextureStateTrackingContext> context_owned(
2702 new TextureStateTrackingContext);
2703 TextureStateTrackingContext* context = context_owned.get();
2705 FakeOutputSurfaceClient output_surface_client;
2706 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
2707 context_owned.PassAs<TestWebGraphicsContext3D>()));
2708 CHECK(output_surface->BindToClient(&output_surface_client));
2710 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
2711 output_surface.get(), shared_bitmap_manager_.get(), 0, false, 1, false));
2713 uint32 sync_point = 30;
2714 unsigned target = GL_TEXTURE_2D;
2716 EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
2717 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
2718 EXPECT_CALL(*context, insertSyncPoint()).Times(0);
2719 EXPECT_CALL(*context, produceTextureCHROMIUM(_, _)).Times(0);
2720 EXPECT_CALL(*context, consumeTextureCHROMIUM(_, _)).Times(0);
2722 gpu::Mailbox gpu_mailbox;
2723 memcpy(gpu_mailbox.name, "Hello world", strlen("Hello world") + 1);
2724 scoped_ptr<SingleReleaseCallback> callback =
2725 SingleReleaseCallback::Create(base::Bind(&EmptyReleaseCallback));
2727 TextureMailbox mailbox(gpu_mailbox, target, sync_point);
2729 ResourceProvider::ResourceId id =
2730 resource_provider->CreateResourceFromTextureMailbox(mailbox,
2731 callback.Pass());
2732 EXPECT_NE(0u, id);
2734 Mock::VerifyAndClearExpectations(context);
2737 // First call to WaitSyncPointIfNeeded should call waitSyncPoint.
2738 EXPECT_CALL(*context, waitSyncPoint(sync_point));
2739 resource_provider->WaitSyncPointIfNeeded(id);
2740 Mock::VerifyAndClearExpectations(context);
2742 // Subsequent calls to WaitSyncPointIfNeeded shouldn't call waitSyncPoint.
2743 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
2744 resource_provider->WaitSyncPointIfNeeded(id);
2745 Mock::VerifyAndClearExpectations(context);
2749 TEST_P(ResourceProviderTest, TextureMailbox_WaitSyncPointIfNeeded_NoSyncPoint) {
2750 // Mailboxing is only supported for GL textures.
2751 if (GetParam() != ResourceProvider::GLTexture)
2752 return;
2754 scoped_ptr<TextureStateTrackingContext> context_owned(
2755 new TextureStateTrackingContext);
2756 TextureStateTrackingContext* context = context_owned.get();
2758 FakeOutputSurfaceClient output_surface_client;
2759 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
2760 context_owned.PassAs<TestWebGraphicsContext3D>()));
2761 CHECK(output_surface->BindToClient(&output_surface_client));
2763 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
2764 output_surface.get(), shared_bitmap_manager_.get(), 0, false, 1, false));
2766 uint32 sync_point = 0;
2767 unsigned target = GL_TEXTURE_2D;
2769 EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
2770 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
2771 EXPECT_CALL(*context, insertSyncPoint()).Times(0);
2772 EXPECT_CALL(*context, produceTextureCHROMIUM(_, _)).Times(0);
2773 EXPECT_CALL(*context, consumeTextureCHROMIUM(_, _)).Times(0);
2775 gpu::Mailbox gpu_mailbox;
2776 memcpy(gpu_mailbox.name, "Hello world", strlen("Hello world") + 1);
2777 scoped_ptr<SingleReleaseCallback> callback =
2778 SingleReleaseCallback::Create(base::Bind(&EmptyReleaseCallback));
2780 TextureMailbox mailbox(gpu_mailbox, target, sync_point);
2782 ResourceProvider::ResourceId id =
2783 resource_provider->CreateResourceFromTextureMailbox(mailbox,
2784 callback.Pass());
2785 EXPECT_NE(0u, id);
2787 Mock::VerifyAndClearExpectations(context);
2790 // WaitSyncPointIfNeeded with sync_point == 0 shouldn't call waitSyncPoint.
2791 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
2792 resource_provider->WaitSyncPointIfNeeded(id);
2793 Mock::VerifyAndClearExpectations(context);
2797 class AllocationTrackingContext3D : public TestWebGraphicsContext3D {
2798 public:
2799 MOCK_METHOD0(NextTextureId, GLuint());
2800 MOCK_METHOD1(RetireTextureId, void(GLuint id));
2801 MOCK_METHOD2(bindTexture, void(GLenum target, GLuint texture));
2802 MOCK_METHOD5(texStorage2DEXT,
2803 void(GLenum target,
2804 GLint levels,
2805 GLuint internalformat,
2806 GLint width,
2807 GLint height));
2808 MOCK_METHOD9(texImage2D,
2809 void(GLenum target,
2810 GLint level,
2811 GLenum internalformat,
2812 GLsizei width,
2813 GLsizei height,
2814 GLint border,
2815 GLenum format,
2816 GLenum type,
2817 const void* pixels));
2818 MOCK_METHOD9(texSubImage2D,
2819 void(GLenum target,
2820 GLint level,
2821 GLint xoffset,
2822 GLint yoffset,
2823 GLsizei width,
2824 GLsizei height,
2825 GLenum format,
2826 GLenum type,
2827 const void* pixels));
2828 MOCK_METHOD9(asyncTexImage2DCHROMIUM,
2829 void(GLenum target,
2830 GLint level,
2831 GLenum internalformat,
2832 GLsizei width,
2833 GLsizei height,
2834 GLint border,
2835 GLenum format,
2836 GLenum type,
2837 const void* pixels));
2838 MOCK_METHOD9(asyncTexSubImage2DCHROMIUM,
2839 void(GLenum target,
2840 GLint level,
2841 GLint xoffset,
2842 GLint yoffset,
2843 GLsizei width,
2844 GLsizei height,
2845 GLenum format,
2846 GLenum type,
2847 const void* pixels));
2848 MOCK_METHOD8(compressedTexImage2D,
2849 void(GLenum target,
2850 GLint level,
2851 GLenum internalformat,
2852 GLsizei width,
2853 GLsizei height,
2854 GLint border,
2855 GLsizei image_size,
2856 const void* data));
2857 MOCK_METHOD1(waitAsyncTexImage2DCHROMIUM, void(GLenum));
2858 MOCK_METHOD4(createImageCHROMIUM, GLuint(GLsizei, GLsizei, GLenum, GLenum));
2859 MOCK_METHOD1(destroyImageCHROMIUM, void(GLuint));
2860 MOCK_METHOD1(mapImageCHROMIUM, void*(GLuint));
2861 MOCK_METHOD3(getImageParameterivCHROMIUM, void(GLuint, GLenum, GLint*));
2862 MOCK_METHOD1(unmapImageCHROMIUM, void(GLuint));
2863 MOCK_METHOD2(bindTexImage2DCHROMIUM, void(GLenum, GLint));
2864 MOCK_METHOD2(releaseTexImage2DCHROMIUM, void(GLenum, GLint));
2866 // We're mocking bindTexture, so we override
2867 // TestWebGraphicsContext3D::texParameteri to avoid assertions related to the
2868 // currently bound texture.
2869 virtual void texParameteri(GLenum target, GLenum pname, GLint param) {}
2872 TEST_P(ResourceProviderTest, TextureAllocation) {
2873 // Only for GL textures.
2874 if (GetParam() != ResourceProvider::GLTexture)
2875 return;
2876 scoped_ptr<AllocationTrackingContext3D> context_owned(
2877 new StrictMock<AllocationTrackingContext3D>);
2878 AllocationTrackingContext3D* context = context_owned.get();
2880 FakeOutputSurfaceClient output_surface_client;
2881 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
2882 context_owned.PassAs<TestWebGraphicsContext3D>()));
2883 CHECK(output_surface->BindToClient(&output_surface_client));
2885 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
2886 output_surface.get(), shared_bitmap_manager_.get(), 0, false, 1, false));
2888 gfx::Size size(2, 2);
2889 gfx::Vector2d offset(0, 0);
2890 gfx::Rect rect(0, 0, 2, 2);
2891 ResourceFormat format = RGBA_8888;
2892 ResourceProvider::ResourceId id = 0;
2893 uint8_t pixels[16] = { 0 };
2894 int texture_id = 123;
2896 // Lazy allocation. Don't allocate when creating the resource.
2897 id = resource_provider->CreateResource(
2898 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
2900 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
2901 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(1);
2902 resource_provider->CreateForTesting(id);
2904 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
2905 resource_provider->DeleteResource(id);
2907 Mock::VerifyAndClearExpectations(context);
2909 // Do allocate when we set the pixels.
2910 id = resource_provider->CreateResource(
2911 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
2913 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
2914 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(3);
2915 EXPECT_CALL(*context, texImage2D(_, _, _, 2, 2, _, _, _, _)).Times(1);
2916 EXPECT_CALL(*context, texSubImage2D(_, _, _, _, 2, 2, _, _, _)).Times(1);
2917 resource_provider->SetPixels(id, pixels, rect, rect, offset);
2919 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
2920 resource_provider->DeleteResource(id);
2922 Mock::VerifyAndClearExpectations(context);
2924 // Same for async version.
2925 id = resource_provider->CreateResource(
2926 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
2927 resource_provider->AcquirePixelRasterBuffer(id);
2929 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
2930 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
2931 EXPECT_CALL(*context, asyncTexImage2DCHROMIUM(_, _, _, 2, 2, _, _, _, _))
2932 .Times(1);
2933 resource_provider->BeginSetPixels(id);
2934 ASSERT_TRUE(resource_provider->DidSetPixelsComplete(id));
2936 resource_provider->ReleasePixelRasterBuffer(id);
2938 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
2939 resource_provider->DeleteResource(id);
2941 Mock::VerifyAndClearExpectations(context);
2944 TEST_P(ResourceProviderTest, TextureAllocationHint) {
2945 // Only for GL textures.
2946 if (GetParam() != ResourceProvider::GLTexture)
2947 return;
2948 scoped_ptr<AllocationTrackingContext3D> context_owned(
2949 new StrictMock<AllocationTrackingContext3D>);
2950 AllocationTrackingContext3D* context = context_owned.get();
2951 context->set_support_texture_storage(true);
2952 context->set_support_texture_usage(true);
2954 FakeOutputSurfaceClient output_surface_client;
2955 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
2956 context_owned.PassAs<TestWebGraphicsContext3D>()));
2957 CHECK(output_surface->BindToClient(&output_surface_client));
2959 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
2960 output_surface.get(), shared_bitmap_manager_.get(), 0, false, 1, false));
2962 gfx::Size size(2, 2);
2963 ResourceFormat format = RGBA_8888;
2965 const ResourceProvider::TextureHint hints[4] = {
2966 ResourceProvider::TextureHintDefault,
2967 ResourceProvider::TextureHintImmutable,
2968 ResourceProvider::TextureHintFramebuffer,
2969 ResourceProvider::TextureHintImmutableFramebuffer,
2971 for (GLuint texture_id = 1; texture_id <= arraysize(hints); ++texture_id) {
2972 // Lazy allocation. Don't allocate when creating the resource.
2973 ResourceProvider::ResourceId id = resource_provider->CreateResource(
2974 size, GL_CLAMP_TO_EDGE, hints[texture_id - 1], format);
2976 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
2977 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
2978 bool is_immutable_hint =
2979 hints[texture_id - 1] & ResourceProvider::TextureHintImmutable;
2980 EXPECT_CALL(*context, texStorage2DEXT(_, _, _, 2, 2))
2981 .Times(is_immutable_hint ? 1 : 0);
2982 EXPECT_CALL(*context, texImage2D(_, _, _, 2, 2, _, _, _, _))
2983 .Times(is_immutable_hint ? 0 : 1);
2984 resource_provider->AllocateForTesting(id);
2986 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
2987 resource_provider->DeleteResource(id);
2989 Mock::VerifyAndClearExpectations(context);
2993 TEST_P(ResourceProviderTest, PixelBuffer_GLTexture) {
2994 if (GetParam() != ResourceProvider::GLTexture)
2995 return;
2996 scoped_ptr<AllocationTrackingContext3D> context_owned(
2997 new StrictMock<AllocationTrackingContext3D>);
2998 AllocationTrackingContext3D* context = context_owned.get();
3000 FakeOutputSurfaceClient output_surface_client;
3001 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
3002 context_owned.PassAs<TestWebGraphicsContext3D>()));
3003 CHECK(output_surface->BindToClient(&output_surface_client));
3005 gfx::Size size(2, 2);
3006 ResourceFormat format = RGBA_8888;
3007 ResourceProvider::ResourceId id = 0;
3008 int texture_id = 123;
3010 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
3011 output_surface.get(), shared_bitmap_manager_.get(), 0, false, 1, false));
3013 id = resource_provider->CreateResource(
3014 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
3015 resource_provider->AcquirePixelRasterBuffer(id);
3017 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3018 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
3019 EXPECT_CALL(*context, asyncTexImage2DCHROMIUM(_, _, _, 2, 2, _, _, _, _))
3020 .Times(1);
3021 resource_provider->BeginSetPixels(id);
3023 EXPECT_TRUE(resource_provider->DidSetPixelsComplete(id));
3025 resource_provider->ReleasePixelRasterBuffer(id);
3027 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3028 resource_provider->DeleteResource(id);
3030 Mock::VerifyAndClearExpectations(context);
3033 TEST_P(ResourceProviderTest, ForcingAsyncUploadToComplete) {
3034 // Only for GL textures.
3035 if (GetParam() != ResourceProvider::GLTexture)
3036 return;
3037 scoped_ptr<AllocationTrackingContext3D> context_owned(
3038 new StrictMock<AllocationTrackingContext3D>);
3039 AllocationTrackingContext3D* context = context_owned.get();
3041 FakeOutputSurfaceClient output_surface_client;
3042 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
3043 context_owned.PassAs<TestWebGraphicsContext3D>()));
3044 CHECK(output_surface->BindToClient(&output_surface_client));
3046 gfx::Size size(2, 2);
3047 ResourceFormat format = RGBA_8888;
3048 ResourceProvider::ResourceId id = 0;
3049 int texture_id = 123;
3051 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
3052 output_surface.get(), shared_bitmap_manager_.get(), 0, false, 1, false));
3054 id = resource_provider->CreateResource(
3055 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
3056 resource_provider->AcquirePixelRasterBuffer(id);
3058 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3059 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
3060 EXPECT_CALL(*context, asyncTexImage2DCHROMIUM(_, _, _, 2, 2, _, _, _, _))
3061 .Times(1);
3062 resource_provider->BeginSetPixels(id);
3064 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(1);
3065 EXPECT_CALL(*context, waitAsyncTexImage2DCHROMIUM(GL_TEXTURE_2D)).Times(1);
3066 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, 0)).Times(1);
3067 resource_provider->ForceSetPixelsToComplete(id);
3069 resource_provider->ReleasePixelRasterBuffer(id);
3071 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3072 resource_provider->DeleteResource(id);
3074 Mock::VerifyAndClearExpectations(context);
3077 TEST_P(ResourceProviderTest, PixelBufferLostContext) {
3078 scoped_ptr<AllocationTrackingContext3D> context_owned(
3079 new NiceMock<AllocationTrackingContext3D>);
3080 AllocationTrackingContext3D* context = context_owned.get();
3082 FakeOutputSurfaceClient output_surface_client;
3083 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
3084 context_owned.PassAs<TestWebGraphicsContext3D>()));
3085 CHECK(output_surface->BindToClient(&output_surface_client));
3087 gfx::Size size(2, 2);
3088 ResourceFormat format = RGBA_8888;
3089 ResourceProvider::ResourceId id = 0;
3090 int texture_id = 123;
3092 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
3093 output_surface.get(), shared_bitmap_manager_.get(), 0, false, 1, false));
3095 EXPECT_CALL(*context, NextTextureId()).WillRepeatedly(Return(texture_id));
3097 id = resource_provider->CreateResource(
3098 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
3099 context->loseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB,
3100 GL_INNOCENT_CONTEXT_RESET_ARB);
3102 resource_provider->AcquirePixelRasterBuffer(id);
3103 SkCanvas* raster_canvas = resource_provider->MapPixelRasterBuffer(id);
3104 EXPECT_TRUE(raster_canvas == NULL);
3105 resource_provider->UnmapPixelRasterBuffer(id);
3106 resource_provider->ReleasePixelRasterBuffer(id);
3107 Mock::VerifyAndClearExpectations(context);
3110 TEST_P(ResourceProviderTest, Image_GLTexture) {
3111 // Only for GL textures.
3112 if (GetParam() != ResourceProvider::GLTexture)
3113 return;
3114 scoped_ptr<AllocationTrackingContext3D> context_owned(
3115 new StrictMock<AllocationTrackingContext3D>);
3116 AllocationTrackingContext3D* context = context_owned.get();
3118 FakeOutputSurfaceClient output_surface_client;
3119 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
3120 context_owned.PassAs<TestWebGraphicsContext3D>()));
3121 CHECK(output_surface->BindToClient(&output_surface_client));
3123 const int kWidth = 2;
3124 const int kHeight = 2;
3125 gfx::Size size(kWidth, kHeight);
3126 ResourceFormat format = RGBA_8888;
3127 ResourceProvider::ResourceId id = 0;
3128 const unsigned kTextureId = 123u;
3129 const unsigned kImageId = 234u;
3131 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
3132 output_surface.get(), shared_bitmap_manager_.get(), 0, false, 1, false));
3134 id = resource_provider->CreateResource(
3135 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
3137 const int kStride = 4;
3138 void* dummy_mapped_buffer_address = NULL;
3139 EXPECT_CALL(
3140 *context,
3141 createImageCHROMIUM(kWidth, kHeight, GL_RGBA8_OES, GL_IMAGE_MAP_CHROMIUM))
3142 .WillOnce(Return(kImageId))
3143 .RetiresOnSaturation();
3144 EXPECT_CALL(*context, getImageParameterivCHROMIUM(kImageId,
3145 GL_IMAGE_ROWBYTES_CHROMIUM,
3147 .WillOnce(SetArgPointee<2>(kStride))
3148 .RetiresOnSaturation();
3149 EXPECT_CALL(*context, mapImageCHROMIUM(kImageId))
3150 .WillOnce(Return(dummy_mapped_buffer_address))
3151 .RetiresOnSaturation();
3152 resource_provider->MapImageRasterBuffer(id);
3154 EXPECT_CALL(*context, unmapImageCHROMIUM(kImageId))
3155 .Times(1)
3156 .RetiresOnSaturation();
3157 resource_provider->UnmapImageRasterBuffer(id);
3159 EXPECT_CALL(*context, NextTextureId())
3160 .WillOnce(Return(kTextureId))
3161 .RetiresOnSaturation();
3162 // Once in CreateTextureId and once in BindForSampling
3163 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kTextureId)).Times(2)
3164 .RetiresOnSaturation();
3165 EXPECT_CALL(*context, bindTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId))
3166 .Times(1)
3167 .RetiresOnSaturation();
3169 ResourceProvider::ScopedSamplerGL lock_gl(
3170 resource_provider.get(), id, GL_TEXTURE_2D, GL_LINEAR);
3171 EXPECT_EQ(kTextureId, lock_gl.texture_id());
3174 EXPECT_CALL(
3175 *context,
3176 getImageParameterivCHROMIUM(kImageId, GL_IMAGE_ROWBYTES_CHROMIUM, _))
3177 .WillOnce(SetArgPointee<2>(kStride))
3178 .RetiresOnSaturation();
3179 EXPECT_CALL(*context, mapImageCHROMIUM(kImageId))
3180 .WillOnce(Return(dummy_mapped_buffer_address))
3181 .RetiresOnSaturation();
3182 resource_provider->MapImageRasterBuffer(id);
3184 EXPECT_CALL(*context, unmapImageCHROMIUM(kImageId))
3185 .Times(1)
3186 .RetiresOnSaturation();
3187 resource_provider->UnmapImageRasterBuffer(id);
3189 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kTextureId)).Times(1)
3190 .RetiresOnSaturation();
3191 EXPECT_CALL(*context, releaseTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId))
3192 .Times(1)
3193 .RetiresOnSaturation();
3194 EXPECT_CALL(*context, bindTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId))
3195 .Times(1)
3196 .RetiresOnSaturation();
3197 EXPECT_CALL(*context, RetireTextureId(kTextureId))
3198 .Times(1)
3199 .RetiresOnSaturation();
3201 ResourceProvider::ScopedSamplerGL lock_gl(
3202 resource_provider.get(), id, GL_TEXTURE_2D, GL_LINEAR);
3203 EXPECT_EQ(kTextureId, lock_gl.texture_id());
3206 EXPECT_CALL(*context, destroyImageCHROMIUM(kImageId))
3207 .Times(1)
3208 .RetiresOnSaturation();
3211 TEST_P(ResourceProviderTest, Image_Bitmap) {
3212 if (GetParam() != ResourceProvider::Bitmap)
3213 return;
3214 FakeOutputSurfaceClient output_surface_client;
3215 scoped_ptr<OutputSurface> output_surface(
3216 FakeOutputSurface::CreateSoftware(make_scoped_ptr(
3217 new SoftwareOutputDevice)));
3218 CHECK(output_surface->BindToClient(&output_surface_client));
3220 gfx::Size size(1, 1);
3221 ResourceFormat format = RGBA_8888;
3222 ResourceProvider::ResourceId id = 0;
3223 const uint32_t kBadBeef = 0xbadbeef;
3225 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
3226 output_surface.get(), shared_bitmap_manager_.get(), 0, false, 1, false));
3228 id = resource_provider->CreateResource(
3229 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
3231 SkBitmap bitmap;
3232 bitmap.allocN32Pixels(size.width(), size.height());
3233 *(bitmap.getAddr32(0, 0)) = kBadBeef;
3234 SkCanvas* canvas = resource_provider->MapImageRasterBuffer(id);
3235 ASSERT_TRUE(!!canvas);
3236 canvas->writePixels(bitmap, 0, 0);
3237 resource_provider->UnmapImageRasterBuffer(id);
3240 ResourceProvider::ScopedReadLockSoftware lock(resource_provider.get(), id);
3241 const SkBitmap* sk_bitmap = lock.sk_bitmap();
3242 EXPECT_EQ(sk_bitmap->width(), size.width());
3243 EXPECT_EQ(sk_bitmap->height(), size.height());
3244 EXPECT_EQ(*sk_bitmap->getAddr32(0, 0), kBadBeef);
3247 resource_provider->DeleteResource(id);
3250 TEST_P(ResourceProviderTest, CopyResource_GLTexture) {
3251 if (GetParam() != ResourceProvider::GLTexture)
3252 return;
3253 scoped_ptr<AllocationTrackingContext3D> context_owned(
3254 new StrictMock<AllocationTrackingContext3D>);
3255 AllocationTrackingContext3D* context = context_owned.get();
3256 context_owned->set_support_sync_query(true);
3258 FakeOutputSurfaceClient output_surface_client;
3259 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
3260 context_owned.PassAs<TestWebGraphicsContext3D>()));
3261 ASSERT_TRUE(output_surface->BindToClient(&output_surface_client));
3263 const int kWidth = 2;
3264 const int kHeight = 2;
3265 gfx::Size size(kWidth, kHeight);
3266 ResourceFormat format = RGBA_8888;
3267 ResourceProvider::ResourceId source_id = 0;
3268 ResourceProvider::ResourceId dest_id = 0;
3269 const unsigned kSourceTextureId = 123u;
3270 const unsigned kDestTextureId = 321u;
3271 const unsigned kImageId = 234u;
3273 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
3274 output_surface.get(), shared_bitmap_manager_.get(), 0, false, 1, false));
3276 source_id = resource_provider->CreateResource(
3277 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
3279 const int kStride = 4;
3280 void* dummy_mapped_buffer_address = NULL;
3281 EXPECT_CALL(
3282 *context,
3283 createImageCHROMIUM(kWidth, kHeight, GL_RGBA8_OES, GL_IMAGE_MAP_CHROMIUM))
3284 .WillOnce(Return(kImageId))
3285 .RetiresOnSaturation();
3286 EXPECT_CALL(
3287 *context,
3288 getImageParameterivCHROMIUM(kImageId, GL_IMAGE_ROWBYTES_CHROMIUM, _))
3289 .WillOnce(SetArgPointee<2>(kStride))
3290 .RetiresOnSaturation();
3291 EXPECT_CALL(*context, mapImageCHROMIUM(kImageId))
3292 .WillOnce(Return(dummy_mapped_buffer_address))
3293 .RetiresOnSaturation();
3294 resource_provider->MapImageRasterBuffer(source_id);
3295 Mock::VerifyAndClearExpectations(context);
3297 EXPECT_CALL(*context, unmapImageCHROMIUM(kImageId))
3298 .Times(1)
3299 .RetiresOnSaturation();
3300 resource_provider->UnmapImageRasterBuffer(source_id);
3301 Mock::VerifyAndClearExpectations(context);
3303 dest_id = resource_provider->CreateResource(
3304 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
3306 EXPECT_CALL(*context, NextTextureId())
3307 .WillOnce(Return(kDestTextureId))
3308 .RetiresOnSaturation();
3309 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kDestTextureId))
3310 .Times(1)
3311 .RetiresOnSaturation();
3312 EXPECT_CALL(*context, NextTextureId())
3313 .WillOnce(Return(kSourceTextureId))
3314 .RetiresOnSaturation();
3315 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kSourceTextureId))
3316 .Times(2)
3317 .RetiresOnSaturation();
3318 EXPECT_CALL(*context, bindTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId))
3319 .Times(1)
3320 .RetiresOnSaturation();
3321 resource_provider->CopyResource(source_id, dest_id);
3322 Mock::VerifyAndClearExpectations(context);
3324 EXPECT_CALL(*context, destroyImageCHROMIUM(kImageId))
3325 .Times(1)
3326 .RetiresOnSaturation();
3327 EXPECT_CALL(*context, RetireTextureId(kSourceTextureId))
3328 .Times(1)
3329 .RetiresOnSaturation();
3330 EXPECT_CALL(*context, RetireTextureId(kDestTextureId))
3331 .Times(1)
3332 .RetiresOnSaturation();
3333 resource_provider->DeleteResource(source_id);
3334 resource_provider->DeleteResource(dest_id);
3337 TEST_P(ResourceProviderTest, CopyResource_Bitmap) {
3338 if (GetParam() != ResourceProvider::Bitmap)
3339 return;
3340 FakeOutputSurfaceClient output_surface_client;
3341 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::CreateSoftware(
3342 make_scoped_ptr(new SoftwareOutputDevice)));
3343 CHECK(output_surface->BindToClient(&output_surface_client));
3345 gfx::Size size(1, 1);
3346 ResourceFormat format = RGBA_8888;
3347 ResourceProvider::ResourceId source_id = 0;
3348 ResourceProvider::ResourceId dest_id = 0;
3349 const uint32_t kBadBeef = 0xbadbeef;
3351 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
3352 output_surface.get(), shared_bitmap_manager_.get(), 0, false, 1, false));
3354 source_id = resource_provider->CreateResource(
3355 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
3357 SkBitmap bitmap;
3358 bitmap.allocN32Pixels(size.width(), size.height());
3359 *(bitmap.getAddr32(0, 0)) = kBadBeef;
3360 SkCanvas* canvas = resource_provider->MapImageRasterBuffer(source_id);
3361 ASSERT_TRUE(!!canvas);
3362 canvas->writePixels(bitmap, 0, 0);
3363 resource_provider->UnmapImageRasterBuffer(source_id);
3365 dest_id = resource_provider->CreateResource(
3366 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
3368 resource_provider->CopyResource(source_id, dest_id);
3371 ResourceProvider::ScopedReadLockSoftware lock(resource_provider.get(),
3372 dest_id);
3373 const SkBitmap* sk_bitmap = lock.sk_bitmap();
3374 EXPECT_EQ(sk_bitmap->width(), size.width());
3375 EXPECT_EQ(sk_bitmap->height(), size.height());
3376 EXPECT_EQ(*sk_bitmap->getAddr32(0, 0), kBadBeef);
3379 resource_provider->DeleteResource(source_id);
3380 resource_provider->DeleteResource(dest_id);
3383 void InitializeGLAndCheck(ContextSharedData* shared_data,
3384 ResourceProvider* resource_provider,
3385 FakeOutputSurface* output_surface) {
3386 scoped_ptr<ResourceProviderContext> context_owned =
3387 ResourceProviderContext::Create(shared_data);
3388 ResourceProviderContext* context = context_owned.get();
3390 scoped_refptr<TestContextProvider> context_provider =
3391 TestContextProvider::Create(
3392 context_owned.PassAs<TestWebGraphicsContext3D>());
3393 output_surface->InitializeAndSetContext3d(context_provider);
3394 resource_provider->InitializeGL();
3396 CheckCreateResource(ResourceProvider::GLTexture, resource_provider, context);
3399 TEST(ResourceProviderTest, BasicInitializeGLSoftware) {
3400 scoped_ptr<ContextSharedData> shared_data = ContextSharedData::Create();
3401 bool delegated_rendering = false;
3402 scoped_ptr<FakeOutputSurface> output_surface(
3403 FakeOutputSurface::CreateDeferredGL(
3404 scoped_ptr<SoftwareOutputDevice>(new SoftwareOutputDevice),
3405 delegated_rendering));
3406 FakeOutputSurfaceClient client(output_surface.get());
3407 EXPECT_TRUE(output_surface->BindToClient(&client));
3408 scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
3409 new TestSharedBitmapManager());
3410 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
3411 output_surface.get(), shared_bitmap_manager.get(), 0, false, 1, false));
3413 CheckCreateResource(ResourceProvider::Bitmap, resource_provider.get(), NULL);
3415 InitializeGLAndCheck(shared_data.get(),
3416 resource_provider.get(),
3417 output_surface.get());
3419 resource_provider->InitializeSoftware();
3420 output_surface->ReleaseGL();
3421 CheckCreateResource(ResourceProvider::Bitmap, resource_provider.get(), NULL);
3423 InitializeGLAndCheck(shared_data.get(),
3424 resource_provider.get(),
3425 output_surface.get());
3428 TEST_P(ResourceProviderTest, CompressedTextureETC1Allocate) {
3429 if (GetParam() != ResourceProvider::GLTexture)
3430 return;
3432 scoped_ptr<AllocationTrackingContext3D> context_owned(
3433 new AllocationTrackingContext3D);
3434 AllocationTrackingContext3D* context = context_owned.get();
3435 context_owned->set_support_compressed_texture_etc1(true);
3437 FakeOutputSurfaceClient output_surface_client;
3438 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
3439 context_owned.PassAs<TestWebGraphicsContext3D>()));
3440 CHECK(output_surface->BindToClient(&output_surface_client));
3442 gfx::Size size(4, 4);
3443 scoped_ptr<ResourceProvider> resource_provider(
3444 ResourceProvider::Create(output_surface.get(),
3445 shared_bitmap_manager_.get(),
3447 false,
3449 false));
3450 int texture_id = 123;
3452 ResourceProvider::ResourceId id = resource_provider->CreateResource(
3453 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, ETC1);
3454 EXPECT_NE(0u, id);
3455 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3456 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
3457 resource_provider->AllocateForTesting(id);
3459 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3460 resource_provider->DeleteResource(id);
3463 TEST_P(ResourceProviderTest, CompressedTextureETC1SetPixels) {
3464 if (GetParam() != ResourceProvider::GLTexture)
3465 return;
3467 scoped_ptr<AllocationTrackingContext3D> context_owned(
3468 new AllocationTrackingContext3D);
3469 AllocationTrackingContext3D* context = context_owned.get();
3470 context_owned->set_support_compressed_texture_etc1(true);
3472 FakeOutputSurfaceClient output_surface_client;
3473 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
3474 context_owned.PassAs<TestWebGraphicsContext3D>()));
3475 CHECK(output_surface->BindToClient(&output_surface_client));
3477 gfx::Size size(4, 4);
3478 scoped_ptr<ResourceProvider> resource_provider(
3479 ResourceProvider::Create(output_surface.get(),
3480 shared_bitmap_manager_.get(),
3482 false,
3484 false));
3485 int texture_id = 123;
3486 uint8_t pixels[8];
3488 ResourceProvider::ResourceId id = resource_provider->CreateResource(
3489 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, ETC1);
3490 EXPECT_NE(0u, id);
3491 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3492 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(3);
3493 EXPECT_CALL(*context,
3494 compressedTexImage2D(
3495 _, 0, _, size.width(), size.height(), _, _, _)).Times(1);
3496 resource_provider->SetPixels(
3497 id, pixels, gfx::Rect(size), gfx::Rect(size), gfx::Vector2d(0, 0));
3499 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3500 resource_provider->DeleteResource(id);
3503 INSTANTIATE_TEST_CASE_P(
3504 ResourceProviderTests,
3505 ResourceProviderTest,
3506 ::testing::Values(ResourceProvider::GLTexture, ResourceProvider::Bitmap));
3508 class TextureIdAllocationTrackingContext : public TestWebGraphicsContext3D {
3509 public:
3510 virtual GLuint NextTextureId() OVERRIDE {
3511 base::AutoLock lock(namespace_->lock);
3512 return namespace_->next_texture_id++;
3514 virtual void RetireTextureId(GLuint) OVERRIDE {}
3515 GLuint PeekTextureId() {
3516 base::AutoLock lock(namespace_->lock);
3517 return namespace_->next_texture_id;
3521 TEST(ResourceProviderTest, TextureAllocationChunkSize) {
3522 scoped_ptr<TextureIdAllocationTrackingContext> context_owned(
3523 new TextureIdAllocationTrackingContext);
3524 TextureIdAllocationTrackingContext* context = context_owned.get();
3526 FakeOutputSurfaceClient output_surface_client;
3527 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
3528 context_owned.PassAs<TestWebGraphicsContext3D>()));
3529 CHECK(output_surface->BindToClient(&output_surface_client));
3530 scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
3531 new TestSharedBitmapManager());
3533 gfx::Size size(1, 1);
3534 ResourceFormat format = RGBA_8888;
3537 size_t kTextureAllocationChunkSize = 1;
3538 scoped_ptr<ResourceProvider> resource_provider(
3539 ResourceProvider::Create(output_surface.get(),
3540 shared_bitmap_manager.get(),
3542 false,
3543 kTextureAllocationChunkSize,
3544 false));
3546 ResourceProvider::ResourceId id = resource_provider->CreateResource(
3547 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
3548 resource_provider->AllocateForTesting(id);
3549 Mock::VerifyAndClearExpectations(context);
3551 DCHECK_EQ(2u, context->PeekTextureId());
3552 resource_provider->DeleteResource(id);
3556 size_t kTextureAllocationChunkSize = 8;
3557 scoped_ptr<ResourceProvider> resource_provider(
3558 ResourceProvider::Create(output_surface.get(),
3559 shared_bitmap_manager.get(),
3561 false,
3562 kTextureAllocationChunkSize,
3563 false));
3565 ResourceProvider::ResourceId id = resource_provider->CreateResource(
3566 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
3567 resource_provider->AllocateForTesting(id);
3568 Mock::VerifyAndClearExpectations(context);
3570 DCHECK_EQ(10u, context->PeekTextureId());
3571 resource_provider->DeleteResource(id);
3575 } // namespace
3576 } // namespace cc