Remove pixel_buffer from Resources
[chromium-blink-merge.git] / cc / resources / resource_provider_unittest.cc
blobf556be33b7e02617aae98f677c395b2602735420
1 // Copyright 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "cc/resources/resource_provider.h"
7 #include <algorithm>
8 #include <map>
9 #include <set>
11 #include "base/bind.h"
12 #include "base/containers/hash_tables.h"
13 #include "base/logging.h"
14 #include "base/memory/ref_counted.h"
15 #include "cc/base/scoped_ptr_deque.h"
16 #include "cc/output/output_surface.h"
17 #include "cc/resources/returned_resource.h"
18 #include "cc/resources/shared_bitmap_manager.h"
19 #include "cc/resources/single_release_callback.h"
20 #include "cc/test/fake_output_surface.h"
21 #include "cc/test/fake_output_surface_client.h"
22 #include "cc/test/test_shared_bitmap_manager.h"
23 #include "cc/test/test_texture.h"
24 #include "cc/test/test_web_graphics_context_3d.h"
25 #include "gpu/GLES2/gl2extchromium.h"
26 #include "testing/gmock/include/gmock/gmock.h"
27 #include "testing/gtest/include/gtest/gtest.h"
28 #include "third_party/khronos/GLES2/gl2.h"
29 #include "third_party/khronos/GLES2/gl2ext.h"
30 #include "ui/gfx/rect.h"
32 using testing::Mock;
33 using testing::NiceMock;
34 using testing::Return;
35 using testing::SetArgPointee;
36 using testing::StrictMock;
37 using testing::_;
39 namespace cc {
40 namespace {
42 static void EmptyReleaseCallback(uint32 sync_point, bool lost_resource) {}
44 static void SharedMemoryReleaseCallback(scoped_ptr<base::SharedMemory> memory,
45 uint32 sync_point,
46 bool lost_resource) {}
48 static void ReleaseTextureMailbox(uint32* release_sync_point,
49 bool* release_lost_resource,
50 uint32 sync_point,
51 bool lost_resource) {
52 *release_sync_point = sync_point;
53 *release_lost_resource = lost_resource;
56 static void ReleaseSharedMemoryCallback(
57 scoped_ptr<base::SharedMemory> shared_memory,
58 bool* release_called,
59 uint32* release_sync_point,
60 bool* lost_resource_result,
61 uint32 sync_point,
62 bool lost_resource) {
63 *release_called = true;
64 *release_sync_point = sync_point;
65 *lost_resource_result = lost_resource;
68 static scoped_ptr<base::SharedMemory> CreateAndFillSharedMemory(
69 const gfx::Size& size,
70 uint32_t value) {
71 scoped_ptr<base::SharedMemory> shared_memory(new base::SharedMemory);
72 CHECK(shared_memory->CreateAndMapAnonymous(4 * size.GetArea()));
73 uint32_t* pixels = reinterpret_cast<uint32_t*>(shared_memory->memory());
74 CHECK(pixels);
75 std::fill_n(pixels, size.GetArea(), value);
76 return shared_memory.Pass();
79 class TextureStateTrackingContext : public TestWebGraphicsContext3D {
80 public:
81 MOCK_METHOD2(bindTexture, void(GLenum target, GLuint texture));
82 MOCK_METHOD3(texParameteri, void(GLenum target, GLenum pname, GLint param));
83 MOCK_METHOD1(waitSyncPoint, void(GLuint sync_point));
84 MOCK_METHOD0(insertSyncPoint, GLuint(void));
85 MOCK_METHOD2(produceTextureCHROMIUM,
86 void(GLenum target, const GLbyte* mailbox));
87 MOCK_METHOD2(consumeTextureCHROMIUM,
88 void(GLenum target, const GLbyte* mailbox));
90 // Force all textures to be consecutive numbers starting at "1",
91 // so we easily can test for them.
92 virtual GLuint NextTextureId() OVERRIDE {
93 base::AutoLock lock(namespace_->lock);
94 return namespace_->next_texture_id++;
96 virtual void RetireTextureId(GLuint) OVERRIDE {}
99 // Shared data between multiple ResourceProviderContext. This contains mailbox
100 // contents as well as information about sync points.
101 class ContextSharedData {
102 public:
103 static scoped_ptr<ContextSharedData> Create() {
104 return make_scoped_ptr(new ContextSharedData());
107 uint32 InsertSyncPoint() { return next_sync_point_++; }
109 void GenMailbox(GLbyte* mailbox) {
110 memset(mailbox, 0, GL_MAILBOX_SIZE_CHROMIUM);
111 memcpy(mailbox, &next_mailbox_, sizeof(next_mailbox_));
112 ++next_mailbox_;
115 void ProduceTexture(const GLbyte* mailbox_name,
116 uint32 sync_point,
117 scoped_refptr<TestTexture> texture) {
118 unsigned mailbox = 0;
119 memcpy(&mailbox, mailbox_name, sizeof(mailbox));
120 ASSERT_TRUE(mailbox && mailbox < next_mailbox_);
121 textures_[mailbox] = texture;
122 ASSERT_LT(sync_point_for_mailbox_[mailbox], sync_point);
123 sync_point_for_mailbox_[mailbox] = sync_point;
126 scoped_refptr<TestTexture> ConsumeTexture(const GLbyte* mailbox_name,
127 uint32 sync_point) {
128 unsigned mailbox = 0;
129 memcpy(&mailbox, mailbox_name, sizeof(mailbox));
130 DCHECK(mailbox && mailbox < next_mailbox_);
132 // If the latest sync point the context has waited on is before the sync
133 // point for when the mailbox was set, pretend we never saw that
134 // ProduceTexture.
135 if (sync_point_for_mailbox_[mailbox] > sync_point) {
136 NOTREACHED();
137 return scoped_refptr<TestTexture>();
139 return textures_[mailbox];
142 private:
143 ContextSharedData() : next_sync_point_(1), next_mailbox_(1) {}
145 uint32 next_sync_point_;
146 unsigned next_mailbox_;
147 typedef base::hash_map<unsigned, scoped_refptr<TestTexture> > TextureMap;
148 TextureMap textures_;
149 base::hash_map<unsigned, uint32> sync_point_for_mailbox_;
152 class ResourceProviderContext : public TestWebGraphicsContext3D {
153 public:
154 static scoped_ptr<ResourceProviderContext> Create(
155 ContextSharedData* shared_data) {
156 return make_scoped_ptr(new ResourceProviderContext(shared_data));
159 virtual GLuint insertSyncPoint() OVERRIDE {
160 uint32 sync_point = shared_data_->InsertSyncPoint();
161 // Commit the produceTextureCHROMIUM calls at this point, so that
162 // they're associated with the sync point.
163 for (PendingProduceTextureList::iterator it =
164 pending_produce_textures_.begin();
165 it != pending_produce_textures_.end();
166 ++it) {
167 shared_data_->ProduceTexture(
168 (*it)->mailbox, sync_point, (*it)->texture);
170 pending_produce_textures_.clear();
171 return sync_point;
174 virtual void waitSyncPoint(GLuint sync_point) OVERRIDE {
175 last_waited_sync_point_ = std::max(sync_point, last_waited_sync_point_);
178 unsigned last_waited_sync_point() const { return last_waited_sync_point_; }
180 virtual void texStorage2DEXT(GLenum target,
181 GLint levels,
182 GLuint internalformat,
183 GLint width,
184 GLint height) OVERRIDE {
185 CheckTextureIsBound(target);
186 ASSERT_EQ(static_cast<unsigned>(GL_TEXTURE_2D), target);
187 ASSERT_EQ(1, levels);
188 GLenum format = GL_RGBA;
189 switch (internalformat) {
190 case GL_RGBA8_OES:
191 break;
192 case GL_BGRA8_EXT:
193 format = GL_BGRA_EXT;
194 break;
195 default:
196 NOTREACHED();
198 AllocateTexture(gfx::Size(width, height), format);
201 virtual void texImage2D(GLenum target,
202 GLint level,
203 GLenum internalformat,
204 GLsizei width,
205 GLsizei height,
206 GLint border,
207 GLenum format,
208 GLenum type,
209 const void* pixels) OVERRIDE {
210 CheckTextureIsBound(target);
211 ASSERT_EQ(static_cast<unsigned>(GL_TEXTURE_2D), target);
212 ASSERT_FALSE(level);
213 ASSERT_EQ(internalformat, format);
214 ASSERT_FALSE(border);
215 ASSERT_EQ(static_cast<unsigned>(GL_UNSIGNED_BYTE), type);
216 AllocateTexture(gfx::Size(width, height), format);
217 if (pixels)
218 SetPixels(0, 0, width, height, pixels);
221 virtual void texSubImage2D(GLenum target,
222 GLint level,
223 GLint xoffset,
224 GLint yoffset,
225 GLsizei width,
226 GLsizei height,
227 GLenum format,
228 GLenum type,
229 const void* pixels) OVERRIDE {
230 CheckTextureIsBound(target);
231 ASSERT_EQ(static_cast<unsigned>(GL_TEXTURE_2D), target);
232 ASSERT_FALSE(level);
233 ASSERT_EQ(static_cast<unsigned>(GL_UNSIGNED_BYTE), type);
235 base::AutoLock lock_for_texture_access(namespace_->lock);
236 ASSERT_EQ(GLDataFormat(BoundTexture(target)->format), format);
238 ASSERT_TRUE(pixels);
239 SetPixels(xoffset, yoffset, width, height, pixels);
242 virtual void genMailboxCHROMIUM(GLbyte* mailbox) OVERRIDE {
243 return shared_data_->GenMailbox(mailbox);
246 virtual void produceTextureCHROMIUM(GLenum target,
247 const GLbyte* mailbox) OVERRIDE {
248 CheckTextureIsBound(target);
250 // Delay moving the texture into the mailbox until the next
251 // InsertSyncPoint, so that it is not visible to other contexts that
252 // haven't waited on that sync point.
253 scoped_ptr<PendingProduceTexture> pending(new PendingProduceTexture);
254 memcpy(pending->mailbox, mailbox, sizeof(pending->mailbox));
255 base::AutoLock lock_for_texture_access(namespace_->lock);
256 pending->texture = BoundTexture(target);
257 pending_produce_textures_.push_back(pending.Pass());
260 virtual void consumeTextureCHROMIUM(GLenum target,
261 const GLbyte* mailbox) OVERRIDE {
262 CheckTextureIsBound(target);
263 base::AutoLock lock_for_texture_access(namespace_->lock);
264 scoped_refptr<TestTexture> texture =
265 shared_data_->ConsumeTexture(mailbox, last_waited_sync_point_);
266 namespace_->textures.Replace(BoundTextureId(target), texture);
269 void GetPixels(const gfx::Size& size,
270 ResourceFormat format,
271 uint8_t* pixels) {
272 CheckTextureIsBound(GL_TEXTURE_2D);
273 base::AutoLock lock_for_texture_access(namespace_->lock);
274 scoped_refptr<TestTexture> texture = BoundTexture(GL_TEXTURE_2D);
275 ASSERT_EQ(texture->size, size);
276 ASSERT_EQ(texture->format, format);
277 memcpy(pixels, texture->data.get(), TextureSizeBytes(size, format));
280 protected:
281 explicit ResourceProviderContext(ContextSharedData* shared_data)
282 : shared_data_(shared_data),
283 last_waited_sync_point_(0) {}
285 private:
286 void AllocateTexture(const gfx::Size& size, GLenum format) {
287 CheckTextureIsBound(GL_TEXTURE_2D);
288 ResourceFormat texture_format = RGBA_8888;
289 switch (format) {
290 case GL_RGBA:
291 texture_format = RGBA_8888;
292 break;
293 case GL_BGRA_EXT:
294 texture_format = BGRA_8888;
295 break;
297 base::AutoLock lock_for_texture_access(namespace_->lock);
298 BoundTexture(GL_TEXTURE_2D)->Reallocate(size, texture_format);
301 void SetPixels(int xoffset,
302 int yoffset,
303 int width,
304 int height,
305 const void* pixels) {
306 CheckTextureIsBound(GL_TEXTURE_2D);
307 base::AutoLock lock_for_texture_access(namespace_->lock);
308 scoped_refptr<TestTexture> texture = BoundTexture(GL_TEXTURE_2D);
309 ASSERT_TRUE(texture->data.get());
310 ASSERT_TRUE(xoffset >= 0 && xoffset + width <= texture->size.width());
311 ASSERT_TRUE(yoffset >= 0 && yoffset + height <= texture->size.height());
312 ASSERT_TRUE(pixels);
313 size_t in_pitch = TextureSizeBytes(gfx::Size(width, 1), texture->format);
314 size_t out_pitch =
315 TextureSizeBytes(gfx::Size(texture->size.width(), 1), texture->format);
316 uint8_t* dest = texture->data.get() + yoffset * out_pitch +
317 TextureSizeBytes(gfx::Size(xoffset, 1), texture->format);
318 const uint8_t* src = static_cast<const uint8_t*>(pixels);
319 for (int i = 0; i < height; ++i) {
320 memcpy(dest, src, in_pitch);
321 dest += out_pitch;
322 src += in_pitch;
326 struct PendingProduceTexture {
327 GLbyte mailbox[GL_MAILBOX_SIZE_CHROMIUM];
328 scoped_refptr<TestTexture> texture;
330 typedef ScopedPtrDeque<PendingProduceTexture> PendingProduceTextureList;
331 ContextSharedData* shared_data_;
332 GLuint last_waited_sync_point_;
333 PendingProduceTextureList pending_produce_textures_;
336 void GetResourcePixels(ResourceProvider* resource_provider,
337 ResourceProviderContext* context,
338 ResourceProvider::ResourceId id,
339 const gfx::Size& size,
340 ResourceFormat format,
341 uint8_t* pixels) {
342 switch (resource_provider->default_resource_type()) {
343 case ResourceProvider::GLTexture: {
344 ResourceProvider::ScopedReadLockGL lock_gl(resource_provider, id);
345 ASSERT_NE(0U, lock_gl.texture_id());
346 context->bindTexture(GL_TEXTURE_2D, lock_gl.texture_id());
347 context->GetPixels(size, format, pixels);
348 break;
350 case ResourceProvider::Bitmap: {
351 ResourceProvider::ScopedReadLockSoftware lock_software(resource_provider,
352 id);
353 memcpy(pixels,
354 lock_software.sk_bitmap()->getPixels(),
355 lock_software.sk_bitmap()->getSize());
356 break;
358 case ResourceProvider::InvalidType:
359 NOTREACHED();
360 break;
364 class ResourceProviderTest
365 : public testing::TestWithParam<ResourceProvider::ResourceType> {
366 public:
367 ResourceProviderTest()
368 : shared_data_(ContextSharedData::Create()),
369 context3d_(NULL),
370 child_context_(NULL) {
371 switch (GetParam()) {
372 case ResourceProvider::GLTexture: {
373 scoped_ptr<ResourceProviderContext> context3d(
374 ResourceProviderContext::Create(shared_data_.get()));
375 context3d_ = context3d.get();
377 scoped_refptr<TestContextProvider> context_provider =
378 TestContextProvider::Create(
379 context3d.PassAs<TestWebGraphicsContext3D>());
381 output_surface_ = FakeOutputSurface::Create3d(context_provider);
383 scoped_ptr<ResourceProviderContext> child_context_owned =
384 ResourceProviderContext::Create(shared_data_.get());
385 child_context_ = child_context_owned.get();
386 child_output_surface_ = FakeOutputSurface::Create3d(
387 child_context_owned.PassAs<TestWebGraphicsContext3D>());
388 break;
390 case ResourceProvider::Bitmap:
391 output_surface_ = FakeOutputSurface::CreateSoftware(
392 make_scoped_ptr(new SoftwareOutputDevice));
393 child_output_surface_ = FakeOutputSurface::CreateSoftware(
394 make_scoped_ptr(new SoftwareOutputDevice));
395 break;
396 case ResourceProvider::InvalidType:
397 NOTREACHED();
398 break;
400 CHECK(output_surface_->BindToClient(&output_surface_client_));
401 CHECK(child_output_surface_->BindToClient(&child_output_surface_client_));
403 shared_bitmap_manager_.reset(new TestSharedBitmapManager());
405 resource_provider_ = ResourceProvider::Create(
406 output_surface_.get(), shared_bitmap_manager_.get(), 0, false, 1);
407 child_resource_provider_ = ResourceProvider::Create(
408 child_output_surface_.get(),
409 shared_bitmap_manager_.get(),
411 false,
415 static void CollectResources(ReturnedResourceArray* array,
416 const ReturnedResourceArray& returned) {
417 array->insert(array->end(), returned.begin(), returned.end());
420 static ReturnCallback GetReturnCallback(ReturnedResourceArray* array) {
421 return base::Bind(&ResourceProviderTest::CollectResources, array);
424 static void SetResourceFilter(ResourceProvider* resource_provider,
425 ResourceProvider::ResourceId id,
426 GLenum filter) {
427 ResourceProvider::ScopedSamplerGL sampler(
428 resource_provider, id, GL_TEXTURE_2D, filter);
431 ResourceProviderContext* context() { return context3d_; }
433 ResourceProvider::ResourceId CreateChildMailbox(uint32* release_sync_point,
434 bool* lost_resource,
435 bool* release_called,
436 uint32* sync_point) {
437 if (GetParam() == ResourceProvider::GLTexture) {
438 unsigned texture = child_context_->createTexture();
439 gpu::Mailbox gpu_mailbox;
440 child_context_->bindTexture(GL_TEXTURE_2D, texture);
441 child_context_->genMailboxCHROMIUM(gpu_mailbox.name);
442 child_context_->produceTextureCHROMIUM(GL_TEXTURE_2D, gpu_mailbox.name);
443 *sync_point = child_context_->insertSyncPoint();
444 EXPECT_LT(0u, *sync_point);
446 scoped_ptr<base::SharedMemory> shared_memory;
447 scoped_ptr<SingleReleaseCallback> callback =
448 SingleReleaseCallback::Create(base::Bind(ReleaseSharedMemoryCallback,
449 base::Passed(&shared_memory),
450 release_called,
451 release_sync_point,
452 lost_resource));
453 return child_resource_provider_->CreateResourceFromTextureMailbox(
454 TextureMailbox(gpu_mailbox, GL_TEXTURE_2D, *sync_point),
455 callback.Pass());
456 } else {
457 gfx::Size size(64, 64);
458 scoped_ptr<base::SharedMemory> shared_memory(
459 CreateAndFillSharedMemory(size, 0));
461 base::SharedMemory* shared_memory_ptr = shared_memory.get();
462 scoped_ptr<SingleReleaseCallback> callback =
463 SingleReleaseCallback::Create(base::Bind(ReleaseSharedMemoryCallback,
464 base::Passed(&shared_memory),
465 release_called,
466 release_sync_point,
467 lost_resource));
468 return child_resource_provider_->CreateResourceFromTextureMailbox(
469 TextureMailbox(shared_memory_ptr, size), callback.Pass());
473 protected:
474 scoped_ptr<ContextSharedData> shared_data_;
475 ResourceProviderContext* context3d_;
476 ResourceProviderContext* child_context_;
477 FakeOutputSurfaceClient output_surface_client_;
478 FakeOutputSurfaceClient child_output_surface_client_;
479 scoped_ptr<OutputSurface> output_surface_;
480 scoped_ptr<OutputSurface> child_output_surface_;
481 scoped_ptr<ResourceProvider> resource_provider_;
482 scoped_ptr<ResourceProvider> child_resource_provider_;
483 scoped_ptr<TestSharedBitmapManager> shared_bitmap_manager_;
486 void CheckCreateResource(ResourceProvider::ResourceType expected_default_type,
487 ResourceProvider* resource_provider,
488 ResourceProviderContext* context) {
489 DCHECK_EQ(expected_default_type, resource_provider->default_resource_type());
491 gfx::Size size(1, 1);
492 ResourceFormat format = RGBA_8888;
493 size_t pixel_size = TextureSizeBytes(size, format);
494 ASSERT_EQ(4U, pixel_size);
496 ResourceProvider::ResourceId id = resource_provider->CreateResource(
497 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
498 EXPECT_EQ(1, static_cast<int>(resource_provider->num_resources()));
499 if (expected_default_type == ResourceProvider::GLTexture)
500 EXPECT_EQ(0u, context->NumTextures());
502 uint8_t data[4] = { 1, 2, 3, 4 };
503 gfx::Rect rect(size);
504 resource_provider->SetPixels(id, data, rect, rect, gfx::Vector2d());
505 if (expected_default_type == ResourceProvider::GLTexture)
506 EXPECT_EQ(1u, context->NumTextures());
508 uint8_t result[4] = { 0 };
509 GetResourcePixels(resource_provider, context, id, size, format, result);
510 EXPECT_EQ(0, memcmp(data, result, pixel_size));
512 resource_provider->DeleteResource(id);
513 EXPECT_EQ(0, static_cast<int>(resource_provider->num_resources()));
514 if (expected_default_type == ResourceProvider::GLTexture)
515 EXPECT_EQ(0u, context->NumTextures());
518 TEST_P(ResourceProviderTest, Basic) {
519 CheckCreateResource(GetParam(), resource_provider_.get(), context());
522 TEST_P(ResourceProviderTest, Upload) {
523 gfx::Size size(2, 2);
524 ResourceFormat format = RGBA_8888;
525 size_t pixel_size = TextureSizeBytes(size, format);
526 ASSERT_EQ(16U, pixel_size);
528 ResourceProvider::ResourceId id = resource_provider_->CreateResource(
529 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
531 uint8_t image[16] = { 0 };
532 gfx::Rect image_rect(size);
533 resource_provider_->SetPixels(
534 id, image, image_rect, image_rect, gfx::Vector2d());
536 for (uint8_t i = 0; i < pixel_size; ++i)
537 image[i] = i;
539 uint8_t result[16] = { 0 };
541 gfx::Rect source_rect(0, 0, 1, 1);
542 gfx::Vector2d dest_offset(0, 0);
543 resource_provider_->SetPixels(
544 id, image, image_rect, source_rect, dest_offset);
546 uint8_t expected[16] = { 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
547 GetResourcePixels(
548 resource_provider_.get(), context(), id, size, format, result);
549 EXPECT_EQ(0, memcmp(expected, result, pixel_size));
552 gfx::Rect source_rect(0, 0, 1, 1);
553 gfx::Vector2d dest_offset(1, 1);
554 resource_provider_->SetPixels(
555 id, image, image_rect, source_rect, dest_offset);
557 uint8_t expected[16] = { 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3 };
558 GetResourcePixels(
559 resource_provider_.get(), context(), id, size, format, result);
560 EXPECT_EQ(0, memcmp(expected, result, pixel_size));
563 gfx::Rect source_rect(1, 0, 1, 1);
564 gfx::Vector2d dest_offset(0, 1);
565 resource_provider_->SetPixels(
566 id, image, image_rect, source_rect, dest_offset);
568 uint8_t expected[16] = { 0, 1, 2, 3, 0, 0, 0, 0, 4, 5, 6, 7, 0, 1, 2, 3 };
569 GetResourcePixels(
570 resource_provider_.get(), context(), id, size, format, result);
571 EXPECT_EQ(0, memcmp(expected, result, pixel_size));
574 gfx::Rect offset_image_rect(gfx::Point(100, 100), size);
575 gfx::Rect source_rect(100, 100, 1, 1);
576 gfx::Vector2d dest_offset(1, 0);
577 resource_provider_->SetPixels(
578 id, image, offset_image_rect, source_rect, dest_offset);
580 uint8_t expected[16] = { 0, 1, 2, 3, 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3 };
581 GetResourcePixels(
582 resource_provider_.get(), context(), id, size, format, result);
583 EXPECT_EQ(0, memcmp(expected, result, pixel_size));
586 resource_provider_->DeleteResource(id);
589 TEST_P(ResourceProviderTest, TransferGLResources) {
590 if (GetParam() != ResourceProvider::GLTexture)
591 return;
592 gfx::Size size(1, 1);
593 ResourceFormat format = RGBA_8888;
594 size_t pixel_size = TextureSizeBytes(size, format);
595 ASSERT_EQ(4U, pixel_size);
597 ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource(
598 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
599 uint8_t data1[4] = { 1, 2, 3, 4 };
600 gfx::Rect rect(size);
601 child_resource_provider_->SetPixels(id1, data1, rect, rect, gfx::Vector2d());
603 ResourceProvider::ResourceId id2 = child_resource_provider_->CreateResource(
604 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
605 uint8_t data2[4] = { 5, 5, 5, 5 };
606 child_resource_provider_->SetPixels(id2, data2, rect, rect, gfx::Vector2d());
608 ResourceProvider::ResourceId id3 = child_resource_provider_->CreateResource(
609 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
610 child_resource_provider_->MapImageRasterBuffer(id3);
611 child_resource_provider_->UnmapImageRasterBuffer(id3);
613 GLuint external_texture_id = child_context_->createExternalTexture();
614 child_context_->bindTexture(GL_TEXTURE_EXTERNAL_OES, external_texture_id);
616 gpu::Mailbox external_mailbox;
617 child_context_->genMailboxCHROMIUM(external_mailbox.name);
618 child_context_->produceTextureCHROMIUM(GL_TEXTURE_EXTERNAL_OES,
619 external_mailbox.name);
620 const GLuint external_sync_point = child_context_->insertSyncPoint();
621 ResourceProvider::ResourceId id4 =
622 child_resource_provider_->CreateResourceFromTextureMailbox(
623 TextureMailbox(
624 external_mailbox, GL_TEXTURE_EXTERNAL_OES, external_sync_point),
625 SingleReleaseCallback::Create(base::Bind(&EmptyReleaseCallback)));
627 ReturnedResourceArray returned_to_child;
628 int child_id =
629 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
631 // Transfer some resources to the parent.
632 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
633 resource_ids_to_transfer.push_back(id1);
634 resource_ids_to_transfer.push_back(id2);
635 resource_ids_to_transfer.push_back(id3);
636 resource_ids_to_transfer.push_back(id4);
637 TransferableResourceArray list;
638 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
639 &list);
640 ASSERT_EQ(4u, list.size());
641 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
642 EXPECT_NE(0u, list[1].mailbox_holder.sync_point);
643 EXPECT_EQ(list[0].mailbox_holder.sync_point,
644 list[1].mailbox_holder.sync_point);
645 EXPECT_NE(0u, list[2].mailbox_holder.sync_point);
646 EXPECT_EQ(list[0].mailbox_holder.sync_point,
647 list[2].mailbox_holder.sync_point);
648 EXPECT_EQ(external_sync_point, list[3].mailbox_holder.sync_point);
649 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
650 list[0].mailbox_holder.texture_target);
651 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
652 list[1].mailbox_holder.texture_target);
653 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
654 list[2].mailbox_holder.texture_target);
655 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_EXTERNAL_OES),
656 list[3].mailbox_holder.texture_target);
657 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
658 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
659 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
660 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id4));
661 resource_provider_->ReceiveFromChild(child_id, list);
662 EXPECT_NE(list[0].mailbox_holder.sync_point,
663 context3d_->last_waited_sync_point());
665 ResourceProvider::ScopedReadLockGL lock(resource_provider_.get(),
666 list[0].id);
668 EXPECT_EQ(list[0].mailbox_holder.sync_point,
669 context3d_->last_waited_sync_point());
670 resource_provider_->DeclareUsedResourcesFromChild(child_id,
671 resource_ids_to_transfer);
674 EXPECT_EQ(4u, resource_provider_->num_resources());
675 ResourceProvider::ResourceIdMap resource_map =
676 resource_provider_->GetChildToParentMap(child_id);
677 ResourceProvider::ResourceId mapped_id1 = resource_map[id1];
678 ResourceProvider::ResourceId mapped_id2 = resource_map[id2];
679 ResourceProvider::ResourceId mapped_id3 = resource_map[id3];
680 ResourceProvider::ResourceId mapped_id4 = resource_map[id4];
681 EXPECT_NE(0u, mapped_id1);
682 EXPECT_NE(0u, mapped_id2);
683 EXPECT_NE(0u, mapped_id3);
684 EXPECT_NE(0u, mapped_id4);
685 EXPECT_FALSE(resource_provider_->InUseByConsumer(id1));
686 EXPECT_FALSE(resource_provider_->InUseByConsumer(id2));
687 EXPECT_FALSE(resource_provider_->InUseByConsumer(id3));
688 EXPECT_FALSE(resource_provider_->InUseByConsumer(id4));
690 uint8_t result[4] = { 0 };
691 GetResourcePixels(
692 resource_provider_.get(), context(), mapped_id1, size, format, result);
693 EXPECT_EQ(0, memcmp(data1, result, pixel_size));
695 GetResourcePixels(
696 resource_provider_.get(), context(), mapped_id2, size, format, result);
697 EXPECT_EQ(0, memcmp(data2, result, pixel_size));
700 // Check that transfering again the same resource from the child to the
701 // parent works.
702 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
703 resource_ids_to_transfer.push_back(id1);
704 resource_ids_to_transfer.push_back(id2);
705 resource_ids_to_transfer.push_back(id3);
706 TransferableResourceArray list;
707 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
708 &list);
709 EXPECT_EQ(3u, list.size());
710 EXPECT_EQ(id1, list[0].id);
711 EXPECT_EQ(id2, list[1].id);
712 EXPECT_EQ(id3, list[2].id);
713 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
714 list[0].mailbox_holder.texture_target);
715 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
716 list[1].mailbox_holder.texture_target);
717 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
718 list[2].mailbox_holder.texture_target);
719 ReturnedResourceArray returned;
720 TransferableResource::ReturnResources(list, &returned);
721 child_resource_provider_->ReceiveReturnsFromParent(returned);
722 // ids were exported twice, we returned them only once, they should still
723 // be in-use.
724 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
725 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
726 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
729 EXPECT_EQ(0u, returned_to_child.size());
731 // Transfer resources back from the parent to the child. Set no resources as
732 // being in use.
733 ResourceProvider::ResourceIdArray no_resources;
734 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
736 ASSERT_EQ(4u, returned_to_child.size());
737 EXPECT_NE(0u, returned_to_child[0].sync_point);
738 EXPECT_NE(0u, returned_to_child[1].sync_point);
739 EXPECT_NE(0u, returned_to_child[2].sync_point);
740 EXPECT_NE(0u, returned_to_child[3].sync_point);
741 EXPECT_FALSE(returned_to_child[0].lost);
742 EXPECT_FALSE(returned_to_child[1].lost);
743 EXPECT_FALSE(returned_to_child[2].lost);
744 EXPECT_FALSE(returned_to_child[3].lost);
745 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
746 returned_to_child.clear();
748 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id1));
749 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id2));
750 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id3));
751 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id4));
754 ResourceProvider::ScopedReadLockGL lock(child_resource_provider_.get(),
755 id1);
756 ASSERT_NE(0U, lock.texture_id());
757 child_context_->bindTexture(GL_TEXTURE_2D, lock.texture_id());
758 child_context_->GetPixels(size, format, result);
759 EXPECT_EQ(0, memcmp(data1, result, pixel_size));
762 ResourceProvider::ScopedReadLockGL lock(child_resource_provider_.get(),
763 id2);
764 ASSERT_NE(0U, lock.texture_id());
765 child_context_->bindTexture(GL_TEXTURE_2D, lock.texture_id());
766 child_context_->GetPixels(size, format, result);
767 EXPECT_EQ(0, memcmp(data2, result, pixel_size));
770 ResourceProvider::ScopedReadLockGL lock(child_resource_provider_.get(),
771 id3);
772 ASSERT_NE(0U, lock.texture_id());
773 child_context_->bindTexture(GL_TEXTURE_2D, lock.texture_id());
776 // Transfer resources to the parent again.
777 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
778 resource_ids_to_transfer.push_back(id1);
779 resource_ids_to_transfer.push_back(id2);
780 resource_ids_to_transfer.push_back(id3);
781 resource_ids_to_transfer.push_back(id4);
782 TransferableResourceArray list;
783 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
784 &list);
785 ASSERT_EQ(4u, list.size());
786 EXPECT_EQ(id1, list[0].id);
787 EXPECT_EQ(id2, list[1].id);
788 EXPECT_EQ(id3, list[2].id);
789 EXPECT_EQ(id4, list[3].id);
790 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
791 EXPECT_NE(0u, list[1].mailbox_holder.sync_point);
792 EXPECT_NE(0u, list[2].mailbox_holder.sync_point);
793 EXPECT_NE(0u, list[3].mailbox_holder.sync_point);
794 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
795 list[0].mailbox_holder.texture_target);
796 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
797 list[1].mailbox_holder.texture_target);
798 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
799 list[2].mailbox_holder.texture_target);
800 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_EXTERNAL_OES),
801 list[3].mailbox_holder.texture_target);
802 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
803 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
804 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
805 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id4));
806 resource_provider_->ReceiveFromChild(child_id, list);
807 resource_provider_->DeclareUsedResourcesFromChild(child_id,
808 resource_ids_to_transfer);
811 EXPECT_EQ(0u, returned_to_child.size());
813 EXPECT_EQ(4u, resource_provider_->num_resources());
814 resource_provider_->DestroyChild(child_id);
815 EXPECT_EQ(0u, resource_provider_->num_resources());
817 ASSERT_EQ(4u, returned_to_child.size());
818 EXPECT_NE(0u, returned_to_child[0].sync_point);
819 EXPECT_NE(0u, returned_to_child[1].sync_point);
820 EXPECT_NE(0u, returned_to_child[2].sync_point);
821 EXPECT_NE(0u, returned_to_child[3].sync_point);
822 EXPECT_FALSE(returned_to_child[0].lost);
823 EXPECT_FALSE(returned_to_child[1].lost);
824 EXPECT_FALSE(returned_to_child[2].lost);
825 EXPECT_FALSE(returned_to_child[3].lost);
828 TEST_P(ResourceProviderTest, ReadLockCountStopsReturnToChildOrDelete) {
829 if (GetParam() != ResourceProvider::GLTexture)
830 return;
831 gfx::Size size(1, 1);
832 ResourceFormat format = RGBA_8888;
834 ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource(
835 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
836 uint8_t data1[4] = {1, 2, 3, 4};
837 gfx::Rect rect(size);
838 child_resource_provider_->SetPixels(id1, data1, rect, rect, gfx::Vector2d());
840 ReturnedResourceArray returned_to_child;
841 int child_id =
842 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
844 // Transfer some resources to the parent.
845 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
846 resource_ids_to_transfer.push_back(id1);
847 TransferableResourceArray list;
848 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
849 &list);
850 ASSERT_EQ(1u, list.size());
851 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
853 resource_provider_->ReceiveFromChild(child_id, list);
855 ResourceProvider::ScopedReadLockGL lock(resource_provider_.get(),
856 list[0].id);
858 resource_provider_->DeclareUsedResourcesFromChild(
859 child_id, ResourceProvider::ResourceIdArray());
860 EXPECT_EQ(0u, returned_to_child.size());
863 EXPECT_EQ(1u, returned_to_child.size());
864 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
867 ResourceProvider::ScopedReadLockGL lock(child_resource_provider_.get(),
868 id1);
869 child_resource_provider_->DeleteResource(id1);
870 EXPECT_EQ(1u, child_resource_provider_->num_resources());
871 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
874 EXPECT_EQ(0u, child_resource_provider_->num_resources());
875 resource_provider_->DestroyChild(child_id);
878 TEST_P(ResourceProviderTest, TransferSoftwareResources) {
879 if (GetParam() != ResourceProvider::Bitmap)
880 return;
882 gfx::Size size(1, 1);
883 ResourceFormat format = RGBA_8888;
884 size_t pixel_size = TextureSizeBytes(size, format);
885 ASSERT_EQ(4U, pixel_size);
887 ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource(
888 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
889 uint8_t data1[4] = { 1, 2, 3, 4 };
890 gfx::Rect rect(size);
891 child_resource_provider_->SetPixels(id1, data1, rect, rect, gfx::Vector2d());
893 ResourceProvider::ResourceId id2 = child_resource_provider_->CreateResource(
894 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
895 uint8_t data2[4] = { 5, 5, 5, 5 };
896 child_resource_provider_->SetPixels(id2, data2, rect, rect, gfx::Vector2d());
898 ResourceProvider::ResourceId id3 = child_resource_provider_->CreateResource(
899 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
900 uint8_t data3[4] = { 6, 7, 8, 9 };
901 SkImageInfo info = SkImageInfo::MakeN32Premul(size.width(), size.height());
902 SkCanvas* raster_canvas = child_resource_provider_->MapImageRasterBuffer(id3);
903 raster_canvas->writePixels(info, data3, info.minRowBytes(), 0, 0);
904 child_resource_provider_->UnmapImageRasterBuffer(id3);
906 scoped_ptr<base::SharedMemory> shared_memory(new base::SharedMemory());
907 shared_memory->CreateAndMapAnonymous(1);
908 base::SharedMemory* shared_memory_ptr = shared_memory.get();
909 ResourceProvider::ResourceId id4 =
910 child_resource_provider_->CreateResourceFromTextureMailbox(
911 TextureMailbox(shared_memory_ptr, gfx::Size(1, 1)),
912 SingleReleaseCallback::Create(base::Bind(
913 &SharedMemoryReleaseCallback, base::Passed(&shared_memory))));
915 ReturnedResourceArray returned_to_child;
916 int child_id =
917 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
919 // Transfer some resources to the parent.
920 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
921 resource_ids_to_transfer.push_back(id1);
922 resource_ids_to_transfer.push_back(id2);
923 resource_ids_to_transfer.push_back(id3);
924 resource_ids_to_transfer.push_back(id4);
925 TransferableResourceArray list;
926 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
927 &list);
928 ASSERT_EQ(4u, list.size());
929 EXPECT_EQ(0u, list[0].mailbox_holder.sync_point);
930 EXPECT_EQ(0u, list[1].mailbox_holder.sync_point);
931 EXPECT_EQ(0u, list[2].mailbox_holder.sync_point);
932 EXPECT_EQ(0u, list[3].mailbox_holder.sync_point);
933 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
934 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
935 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
936 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id4));
937 resource_provider_->ReceiveFromChild(child_id, list);
938 resource_provider_->DeclareUsedResourcesFromChild(child_id,
939 resource_ids_to_transfer);
942 EXPECT_EQ(4u, resource_provider_->num_resources());
943 ResourceProvider::ResourceIdMap resource_map =
944 resource_provider_->GetChildToParentMap(child_id);
945 ResourceProvider::ResourceId mapped_id1 = resource_map[id1];
946 ResourceProvider::ResourceId mapped_id2 = resource_map[id2];
947 ResourceProvider::ResourceId mapped_id3 = resource_map[id3];
948 ResourceProvider::ResourceId mapped_id4 = resource_map[id4];
949 EXPECT_NE(0u, mapped_id1);
950 EXPECT_NE(0u, mapped_id2);
951 EXPECT_NE(0u, mapped_id3);
952 EXPECT_NE(0u, mapped_id4);
953 EXPECT_FALSE(resource_provider_->InUseByConsumer(id1));
954 EXPECT_FALSE(resource_provider_->InUseByConsumer(id2));
955 EXPECT_FALSE(resource_provider_->InUseByConsumer(id3));
956 EXPECT_FALSE(resource_provider_->InUseByConsumer(id4));
958 uint8_t result[4] = { 0 };
959 GetResourcePixels(
960 resource_provider_.get(), context(), mapped_id1, size, format, result);
961 EXPECT_EQ(0, memcmp(data1, result, pixel_size));
963 GetResourcePixels(
964 resource_provider_.get(), context(), mapped_id2, size, format, result);
965 EXPECT_EQ(0, memcmp(data2, result, pixel_size));
967 GetResourcePixels(
968 resource_provider_.get(), context(), mapped_id3, size, format, result);
969 EXPECT_EQ(0, memcmp(data3, result, pixel_size));
972 // Check that transfering again the same resource from the child to the
973 // parent works.
974 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
975 resource_ids_to_transfer.push_back(id1);
976 resource_ids_to_transfer.push_back(id2);
977 resource_ids_to_transfer.push_back(id3);
978 TransferableResourceArray list;
979 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
980 &list);
981 EXPECT_EQ(3u, list.size());
982 EXPECT_EQ(id1, list[0].id);
983 EXPECT_EQ(id2, list[1].id);
984 EXPECT_EQ(id3, list[2].id);
985 ReturnedResourceArray returned;
986 TransferableResource::ReturnResources(list, &returned);
987 child_resource_provider_->ReceiveReturnsFromParent(returned);
988 // ids were exported twice, we returned them only once, they should still
989 // be in-use.
990 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
991 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
992 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
995 EXPECT_EQ(0u, returned_to_child.size());
997 // Transfer resources back from the parent to the child. Set no resources as
998 // being in use.
999 ResourceProvider::ResourceIdArray no_resources;
1000 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
1002 ASSERT_EQ(4u, returned_to_child.size());
1003 EXPECT_EQ(0u, returned_to_child[0].sync_point);
1004 EXPECT_EQ(0u, returned_to_child[1].sync_point);
1005 EXPECT_EQ(0u, returned_to_child[2].sync_point);
1006 EXPECT_EQ(0u, returned_to_child[3].sync_point);
1007 std::set<ResourceProvider::ResourceId> expected_ids;
1008 expected_ids.insert(id1);
1009 expected_ids.insert(id2);
1010 expected_ids.insert(id3);
1011 expected_ids.insert(id4);
1012 std::set<ResourceProvider::ResourceId> returned_ids;
1013 for (unsigned i = 0; i < 4; i++)
1014 returned_ids.insert(returned_to_child[i].id);
1015 EXPECT_EQ(expected_ids, returned_ids);
1016 EXPECT_FALSE(returned_to_child[0].lost);
1017 EXPECT_FALSE(returned_to_child[1].lost);
1018 EXPECT_FALSE(returned_to_child[2].lost);
1019 EXPECT_FALSE(returned_to_child[3].lost);
1020 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
1021 returned_to_child.clear();
1023 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id1));
1024 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id2));
1025 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id3));
1026 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id4));
1029 ResourceProvider::ScopedReadLockSoftware lock(
1030 child_resource_provider_.get(), id1);
1031 const SkBitmap* sk_bitmap = lock.sk_bitmap();
1032 EXPECT_EQ(sk_bitmap->width(), size.width());
1033 EXPECT_EQ(sk_bitmap->height(), size.height());
1034 EXPECT_EQ(0, memcmp(data1, sk_bitmap->getPixels(), pixel_size));
1037 ResourceProvider::ScopedReadLockSoftware lock(
1038 child_resource_provider_.get(), id2);
1039 const SkBitmap* sk_bitmap = lock.sk_bitmap();
1040 EXPECT_EQ(sk_bitmap->width(), size.width());
1041 EXPECT_EQ(sk_bitmap->height(), size.height());
1042 EXPECT_EQ(0, memcmp(data2, sk_bitmap->getPixels(), pixel_size));
1045 ResourceProvider::ScopedReadLockSoftware lock(
1046 child_resource_provider_.get(), id3);
1047 const SkBitmap* sk_bitmap = lock.sk_bitmap();
1048 EXPECT_EQ(sk_bitmap->width(), size.width());
1049 EXPECT_EQ(sk_bitmap->height(), size.height());
1050 EXPECT_EQ(0, memcmp(data3, sk_bitmap->getPixels(), pixel_size));
1053 // Transfer resources to the parent again.
1054 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1055 resource_ids_to_transfer.push_back(id1);
1056 resource_ids_to_transfer.push_back(id2);
1057 resource_ids_to_transfer.push_back(id3);
1058 resource_ids_to_transfer.push_back(id4);
1059 TransferableResourceArray list;
1060 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1061 &list);
1062 ASSERT_EQ(4u, list.size());
1063 EXPECT_EQ(id1, list[0].id);
1064 EXPECT_EQ(id2, list[1].id);
1065 EXPECT_EQ(id3, list[2].id);
1066 EXPECT_EQ(id4, list[3].id);
1067 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1068 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
1069 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
1070 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id4));
1071 resource_provider_->ReceiveFromChild(child_id, list);
1072 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1073 resource_ids_to_transfer);
1076 EXPECT_EQ(0u, returned_to_child.size());
1078 EXPECT_EQ(4u, resource_provider_->num_resources());
1079 resource_provider_->DestroyChild(child_id);
1080 EXPECT_EQ(0u, resource_provider_->num_resources());
1082 ASSERT_EQ(4u, returned_to_child.size());
1083 EXPECT_EQ(0u, returned_to_child[0].sync_point);
1084 EXPECT_EQ(0u, returned_to_child[1].sync_point);
1085 EXPECT_EQ(0u, returned_to_child[2].sync_point);
1086 EXPECT_EQ(0u, returned_to_child[3].sync_point);
1087 std::set<ResourceProvider::ResourceId> expected_ids;
1088 expected_ids.insert(id1);
1089 expected_ids.insert(id2);
1090 expected_ids.insert(id3);
1091 expected_ids.insert(id4);
1092 std::set<ResourceProvider::ResourceId> returned_ids;
1093 for (unsigned i = 0; i < 4; i++)
1094 returned_ids.insert(returned_to_child[i].id);
1095 EXPECT_EQ(expected_ids, returned_ids);
1096 EXPECT_FALSE(returned_to_child[0].lost);
1097 EXPECT_FALSE(returned_to_child[1].lost);
1098 EXPECT_FALSE(returned_to_child[2].lost);
1099 EXPECT_FALSE(returned_to_child[3].lost);
1102 TEST_P(ResourceProviderTest, TransferGLToSoftware) {
1103 if (GetParam() != ResourceProvider::Bitmap)
1104 return;
1106 scoped_ptr<ResourceProviderContext> child_context_owned(
1107 ResourceProviderContext::Create(shared_data_.get()));
1109 FakeOutputSurfaceClient child_output_surface_client;
1110 scoped_ptr<OutputSurface> child_output_surface(FakeOutputSurface::Create3d(
1111 child_context_owned.PassAs<TestWebGraphicsContext3D>()));
1112 CHECK(child_output_surface->BindToClient(&child_output_surface_client));
1114 scoped_ptr<ResourceProvider> child_resource_provider(ResourceProvider::Create(
1115 child_output_surface.get(), shared_bitmap_manager_.get(), 0, false, 1));
1117 gfx::Size size(1, 1);
1118 ResourceFormat format = RGBA_8888;
1119 size_t pixel_size = TextureSizeBytes(size, format);
1120 ASSERT_EQ(4U, pixel_size);
1122 ResourceProvider::ResourceId id1 = child_resource_provider->CreateResource(
1123 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
1124 uint8_t data1[4] = { 1, 2, 3, 4 };
1125 gfx::Rect rect(size);
1126 child_resource_provider->SetPixels(id1, data1, rect, rect, gfx::Vector2d());
1128 ReturnedResourceArray returned_to_child;
1129 int child_id =
1130 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1132 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1133 resource_ids_to_transfer.push_back(id1);
1134 TransferableResourceArray list;
1135 child_resource_provider->PrepareSendToParent(resource_ids_to_transfer,
1136 &list);
1137 ASSERT_EQ(1u, list.size());
1138 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
1139 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
1140 list[0].mailbox_holder.texture_target);
1141 EXPECT_TRUE(child_resource_provider->InUseByConsumer(id1));
1142 resource_provider_->ReceiveFromChild(child_id, list);
1145 EXPECT_EQ(0u, resource_provider_->num_resources());
1146 ASSERT_EQ(1u, returned_to_child.size());
1147 EXPECT_EQ(returned_to_child[0].id, id1);
1148 ResourceProvider::ResourceIdMap resource_map =
1149 resource_provider_->GetChildToParentMap(child_id);
1150 ResourceProvider::ResourceId mapped_id1 = resource_map[id1];
1151 EXPECT_EQ(0u, mapped_id1);
1153 resource_provider_->DestroyChild(child_id);
1154 EXPECT_EQ(0u, resource_provider_->num_resources());
1156 ASSERT_EQ(1u, returned_to_child.size());
1157 EXPECT_FALSE(returned_to_child[0].lost);
1160 TEST_P(ResourceProviderTest, TransferInvalidSoftware) {
1161 if (GetParam() != ResourceProvider::Bitmap)
1162 return;
1164 gfx::Size size(1, 1);
1165 ResourceFormat format = RGBA_8888;
1166 size_t pixel_size = TextureSizeBytes(size, format);
1167 ASSERT_EQ(4U, pixel_size);
1169 ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource(
1170 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
1171 uint8_t data1[4] = { 1, 2, 3, 4 };
1172 gfx::Rect rect(size);
1173 child_resource_provider_->SetPixels(id1, data1, rect, rect, gfx::Vector2d());
1175 ReturnedResourceArray returned_to_child;
1176 int child_id =
1177 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1179 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1180 resource_ids_to_transfer.push_back(id1);
1181 TransferableResourceArray list;
1182 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1183 &list);
1184 ASSERT_EQ(1u, list.size());
1185 // Make invalid.
1186 list[0].mailbox_holder.mailbox.name[1] = 5;
1187 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1188 resource_provider_->ReceiveFromChild(child_id, list);
1191 EXPECT_EQ(1u, resource_provider_->num_resources());
1192 EXPECT_EQ(0u, returned_to_child.size());
1194 ResourceProvider::ResourceIdMap resource_map =
1195 resource_provider_->GetChildToParentMap(child_id);
1196 ResourceProvider::ResourceId mapped_id1 = resource_map[id1];
1197 EXPECT_NE(0u, mapped_id1);
1199 ResourceProvider::ScopedReadLockSoftware lock(resource_provider_.get(),
1200 mapped_id1);
1201 EXPECT_FALSE(lock.valid());
1204 resource_provider_->DestroyChild(child_id);
1205 EXPECT_EQ(0u, resource_provider_->num_resources());
1207 ASSERT_EQ(1u, returned_to_child.size());
1208 EXPECT_FALSE(returned_to_child[0].lost);
1211 TEST_P(ResourceProviderTest, DeleteExportedResources) {
1212 gfx::Size size(1, 1);
1213 ResourceFormat format = RGBA_8888;
1214 size_t pixel_size = TextureSizeBytes(size, format);
1215 ASSERT_EQ(4U, pixel_size);
1217 ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource(
1218 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
1219 uint8_t data1[4] = { 1, 2, 3, 4 };
1220 gfx::Rect rect(size);
1221 child_resource_provider_->SetPixels(id1, data1, rect, rect, gfx::Vector2d());
1223 ResourceProvider::ResourceId id2 = child_resource_provider_->CreateResource(
1224 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
1225 uint8_t data2[4] = {5, 5, 5, 5};
1226 child_resource_provider_->SetPixels(id2, data2, rect, rect, gfx::Vector2d());
1228 ReturnedResourceArray returned_to_child;
1229 int child_id =
1230 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1232 // Transfer some resources to the parent.
1233 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1234 resource_ids_to_transfer.push_back(id1);
1235 resource_ids_to_transfer.push_back(id2);
1236 TransferableResourceArray list;
1237 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1238 &list);
1239 ASSERT_EQ(2u, list.size());
1240 if (GetParam() == ResourceProvider::GLTexture) {
1241 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
1242 EXPECT_NE(0u, list[1].mailbox_holder.sync_point);
1244 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1245 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
1246 resource_provider_->ReceiveFromChild(child_id, list);
1247 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1248 resource_ids_to_transfer);
1251 EXPECT_EQ(2u, resource_provider_->num_resources());
1252 ResourceProvider::ResourceIdMap resource_map =
1253 resource_provider_->GetChildToParentMap(child_id);
1254 ResourceProvider::ResourceId mapped_id1 = resource_map[id1];
1255 ResourceProvider::ResourceId mapped_id2 = resource_map[id2];
1256 EXPECT_NE(0u, mapped_id1);
1257 EXPECT_NE(0u, mapped_id2);
1258 EXPECT_FALSE(resource_provider_->InUseByConsumer(id1));
1259 EXPECT_FALSE(resource_provider_->InUseByConsumer(id2));
1262 // The parent transfers the resources to the grandparent.
1263 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1264 resource_ids_to_transfer.push_back(mapped_id1);
1265 resource_ids_to_transfer.push_back(mapped_id2);
1266 TransferableResourceArray list;
1267 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
1269 ASSERT_EQ(2u, list.size());
1270 if (GetParam() == ResourceProvider::GLTexture) {
1271 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
1272 EXPECT_NE(0u, list[1].mailbox_holder.sync_point);
1274 EXPECT_TRUE(resource_provider_->InUseByConsumer(id1));
1275 EXPECT_TRUE(resource_provider_->InUseByConsumer(id2));
1277 // Release the resource in the parent. Set no resources as being in use. The
1278 // resources are exported so that can't be transferred back yet.
1279 ResourceProvider::ResourceIdArray no_resources;
1280 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
1282 EXPECT_EQ(0u, returned_to_child.size());
1283 EXPECT_EQ(2u, resource_provider_->num_resources());
1285 // Return the resources from the grandparent to the parent. They should be
1286 // returned to the child then.
1287 EXPECT_EQ(2u, list.size());
1288 EXPECT_EQ(mapped_id1, list[0].id);
1289 EXPECT_EQ(mapped_id2, list[1].id);
1290 ReturnedResourceArray returned;
1291 TransferableResource::ReturnResources(list, &returned);
1292 resource_provider_->ReceiveReturnsFromParent(returned);
1294 EXPECT_EQ(0u, resource_provider_->num_resources());
1295 ASSERT_EQ(2u, returned_to_child.size());
1296 if (GetParam() == ResourceProvider::GLTexture) {
1297 EXPECT_NE(0u, returned_to_child[0].sync_point);
1298 EXPECT_NE(0u, returned_to_child[1].sync_point);
1300 EXPECT_FALSE(returned_to_child[0].lost);
1301 EXPECT_FALSE(returned_to_child[1].lost);
1305 TEST_P(ResourceProviderTest, DestroyChildWithExportedResources) {
1306 gfx::Size size(1, 1);
1307 ResourceFormat format = RGBA_8888;
1308 size_t pixel_size = TextureSizeBytes(size, format);
1309 ASSERT_EQ(4U, pixel_size);
1311 ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource(
1312 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
1313 uint8_t data1[4] = {1, 2, 3, 4};
1314 gfx::Rect rect(size);
1315 child_resource_provider_->SetPixels(id1, data1, rect, rect, gfx::Vector2d());
1317 ResourceProvider::ResourceId id2 = child_resource_provider_->CreateResource(
1318 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
1319 uint8_t data2[4] = {5, 5, 5, 5};
1320 child_resource_provider_->SetPixels(id2, data2, rect, rect, gfx::Vector2d());
1322 ReturnedResourceArray returned_to_child;
1323 int child_id =
1324 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1326 // Transfer some resources to the parent.
1327 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1328 resource_ids_to_transfer.push_back(id1);
1329 resource_ids_to_transfer.push_back(id2);
1330 TransferableResourceArray list;
1331 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1332 &list);
1333 ASSERT_EQ(2u, list.size());
1334 if (GetParam() == ResourceProvider::GLTexture) {
1335 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
1336 EXPECT_NE(0u, list[1].mailbox_holder.sync_point);
1338 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1339 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
1340 resource_provider_->ReceiveFromChild(child_id, list);
1341 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1342 resource_ids_to_transfer);
1345 EXPECT_EQ(2u, resource_provider_->num_resources());
1346 ResourceProvider::ResourceIdMap resource_map =
1347 resource_provider_->GetChildToParentMap(child_id);
1348 ResourceProvider::ResourceId mapped_id1 = resource_map[id1];
1349 ResourceProvider::ResourceId mapped_id2 = resource_map[id2];
1350 EXPECT_NE(0u, mapped_id1);
1351 EXPECT_NE(0u, mapped_id2);
1352 EXPECT_FALSE(resource_provider_->InUseByConsumer(id1));
1353 EXPECT_FALSE(resource_provider_->InUseByConsumer(id2));
1356 // The parent transfers the resources to the grandparent.
1357 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1358 resource_ids_to_transfer.push_back(mapped_id1);
1359 resource_ids_to_transfer.push_back(mapped_id2);
1360 TransferableResourceArray list;
1361 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
1363 ASSERT_EQ(2u, list.size());
1364 if (GetParam() == ResourceProvider::GLTexture) {
1365 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
1366 EXPECT_NE(0u, list[1].mailbox_holder.sync_point);
1368 EXPECT_TRUE(resource_provider_->InUseByConsumer(id1));
1369 EXPECT_TRUE(resource_provider_->InUseByConsumer(id2));
1371 // Release the resource in the parent. Set no resources as being in use. The
1372 // resources are exported so that can't be transferred back yet.
1373 ResourceProvider::ResourceIdArray no_resources;
1374 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
1376 // Destroy the child, the resources should not be returned yet.
1377 EXPECT_EQ(0u, returned_to_child.size());
1378 EXPECT_EQ(2u, resource_provider_->num_resources());
1380 resource_provider_->DestroyChild(child_id);
1382 EXPECT_EQ(2u, resource_provider_->num_resources());
1383 ASSERT_EQ(0u, returned_to_child.size());
1385 // Return a resource from the grandparent, it should be returned at this
1386 // point.
1387 EXPECT_EQ(2u, list.size());
1388 EXPECT_EQ(mapped_id1, list[0].id);
1389 EXPECT_EQ(mapped_id2, list[1].id);
1390 TransferableResourceArray return_list;
1391 return_list.push_back(list[1]);
1392 list.pop_back();
1393 ReturnedResourceArray returned;
1394 TransferableResource::ReturnResources(return_list, &returned);
1395 resource_provider_->ReceiveReturnsFromParent(returned);
1397 EXPECT_EQ(1u, resource_provider_->num_resources());
1398 ASSERT_EQ(1u, returned_to_child.size());
1399 if (GetParam() == ResourceProvider::GLTexture) {
1400 EXPECT_NE(0u, returned_to_child[0].sync_point);
1402 EXPECT_FALSE(returned_to_child[0].lost);
1403 returned_to_child.clear();
1405 // Destroy the parent resource provider. The resource that's left should be
1406 // lost at this point, and returned.
1407 resource_provider_.reset();
1408 ASSERT_EQ(1u, returned_to_child.size());
1409 if (GetParam() == ResourceProvider::GLTexture) {
1410 EXPECT_NE(0u, returned_to_child[0].sync_point);
1412 EXPECT_TRUE(returned_to_child[0].lost);
1416 TEST_P(ResourceProviderTest, DeleteTransferredResources) {
1417 gfx::Size size(1, 1);
1418 ResourceFormat format = RGBA_8888;
1419 size_t pixel_size = TextureSizeBytes(size, format);
1420 ASSERT_EQ(4U, pixel_size);
1422 ResourceProvider::ResourceId id = child_resource_provider_->CreateResource(
1423 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
1424 uint8_t data[4] = { 1, 2, 3, 4 };
1425 gfx::Rect rect(size);
1426 child_resource_provider_->SetPixels(id, data, rect, rect, gfx::Vector2d());
1428 ReturnedResourceArray returned_to_child;
1429 int child_id =
1430 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1432 // Transfer some resource to the parent.
1433 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1434 resource_ids_to_transfer.push_back(id);
1435 TransferableResourceArray list;
1436 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1437 &list);
1438 ASSERT_EQ(1u, list.size());
1439 if (GetParam() == ResourceProvider::GLTexture)
1440 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
1441 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id));
1442 resource_provider_->ReceiveFromChild(child_id, list);
1443 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1444 resource_ids_to_transfer);
1447 // Delete textures in the child, while they are transfered.
1448 child_resource_provider_->DeleteResource(id);
1449 EXPECT_EQ(1u, child_resource_provider_->num_resources());
1451 EXPECT_EQ(0u, returned_to_child.size());
1453 // Transfer resources back from the parent to the child. Set no resources as
1454 // being in use.
1455 ResourceProvider::ResourceIdArray no_resources;
1456 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
1458 ASSERT_EQ(1u, returned_to_child.size());
1459 if (GetParam() == ResourceProvider::GLTexture)
1460 EXPECT_NE(0u, returned_to_child[0].sync_point);
1461 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
1463 EXPECT_EQ(0u, child_resource_provider_->num_resources());
1466 TEST_P(ResourceProviderTest, UnuseTransferredResources) {
1467 gfx::Size size(1, 1);
1468 ResourceFormat format = RGBA_8888;
1469 size_t pixel_size = TextureSizeBytes(size, format);
1470 ASSERT_EQ(4U, pixel_size);
1472 ResourceProvider::ResourceId id = child_resource_provider_->CreateResource(
1473 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
1474 uint8_t data[4] = {1, 2, 3, 4};
1475 gfx::Rect rect(size);
1476 child_resource_provider_->SetPixels(id, data, rect, rect, gfx::Vector2d());
1478 ReturnedResourceArray returned_to_child;
1479 int child_id =
1480 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1481 const ResourceProvider::ResourceIdMap& map =
1482 resource_provider_->GetChildToParentMap(child_id);
1484 // Transfer some resource to the parent.
1485 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1486 resource_ids_to_transfer.push_back(id);
1487 TransferableResourceArray list;
1488 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1489 &list);
1490 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id));
1491 resource_provider_->ReceiveFromChild(child_id, list);
1492 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1493 resource_ids_to_transfer);
1495 TransferableResourceArray sent_to_top_level;
1497 // Parent transfers to top-level.
1498 ASSERT_TRUE(map.find(id) != map.end());
1499 ResourceProvider::ResourceId parent_id = map.find(id)->second;
1500 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1501 resource_ids_to_transfer.push_back(parent_id);
1502 resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1503 &sent_to_top_level);
1504 EXPECT_TRUE(resource_provider_->InUseByConsumer(parent_id));
1507 // Stop using resource.
1508 ResourceProvider::ResourceIdArray empty;
1509 resource_provider_->DeclareUsedResourcesFromChild(child_id, empty);
1510 // Resource is not yet returned to the child, since it's in use by the
1511 // top-level.
1512 EXPECT_TRUE(returned_to_child.empty());
1515 // Send the resource to the parent again.
1516 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1517 resource_ids_to_transfer.push_back(id);
1518 TransferableResourceArray list;
1519 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1520 &list);
1521 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id));
1522 resource_provider_->ReceiveFromChild(child_id, list);
1523 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1524 resource_ids_to_transfer);
1527 // Receive returns back from top-level.
1528 ReturnedResourceArray returned;
1529 TransferableResource::ReturnResources(sent_to_top_level, &returned);
1530 resource_provider_->ReceiveReturnsFromParent(returned);
1531 // Resource is still not yet returned to the child, since it's declared used
1532 // in the parent.
1533 EXPECT_TRUE(returned_to_child.empty());
1534 ASSERT_TRUE(map.find(id) != map.end());
1535 ResourceProvider::ResourceId parent_id = map.find(id)->second;
1536 EXPECT_FALSE(resource_provider_->InUseByConsumer(parent_id));
1539 sent_to_top_level.clear();
1540 // Parent transfers again to top-level.
1541 ASSERT_TRUE(map.find(id) != map.end());
1542 ResourceProvider::ResourceId parent_id = map.find(id)->second;
1543 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1544 resource_ids_to_transfer.push_back(parent_id);
1545 resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1546 &sent_to_top_level);
1547 EXPECT_TRUE(resource_provider_->InUseByConsumer(parent_id));
1550 // Receive returns back from top-level.
1551 ReturnedResourceArray returned;
1552 TransferableResource::ReturnResources(sent_to_top_level, &returned);
1553 resource_provider_->ReceiveReturnsFromParent(returned);
1554 // Resource is still not yet returned to the child, since it's still
1555 // declared used in the parent.
1556 EXPECT_TRUE(returned_to_child.empty());
1557 ASSERT_TRUE(map.find(id) != map.end());
1558 ResourceProvider::ResourceId parent_id = map.find(id)->second;
1559 EXPECT_FALSE(resource_provider_->InUseByConsumer(parent_id));
1562 // Stop using resource.
1563 ResourceProvider::ResourceIdArray empty;
1564 resource_provider_->DeclareUsedResourcesFromChild(child_id, empty);
1565 // Resource should have been returned to the child, since it's no longer in
1566 // use by the top-level.
1567 ASSERT_EQ(1u, returned_to_child.size());
1568 EXPECT_EQ(id, returned_to_child[0].id);
1569 EXPECT_EQ(2, returned_to_child[0].count);
1570 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
1571 returned_to_child.clear();
1572 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id));
1576 class ResourceProviderTestTextureFilters : public ResourceProviderTest {
1577 public:
1578 static void RunTest(GLenum child_filter, GLenum parent_filter) {
1579 scoped_ptr<TextureStateTrackingContext> child_context_owned(
1580 new TextureStateTrackingContext);
1581 TextureStateTrackingContext* child_context = child_context_owned.get();
1583 FakeOutputSurfaceClient child_output_surface_client;
1584 scoped_ptr<OutputSurface> child_output_surface(FakeOutputSurface::Create3d(
1585 child_context_owned.PassAs<TestWebGraphicsContext3D>()));
1586 CHECK(child_output_surface->BindToClient(&child_output_surface_client));
1587 scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
1588 new TestSharedBitmapManager());
1590 scoped_ptr<ResourceProvider> child_resource_provider(
1591 ResourceProvider::Create(child_output_surface.get(),
1592 shared_bitmap_manager.get(),
1594 false,
1595 1));
1597 scoped_ptr<TextureStateTrackingContext> parent_context_owned(
1598 new TextureStateTrackingContext);
1599 TextureStateTrackingContext* parent_context = parent_context_owned.get();
1601 FakeOutputSurfaceClient parent_output_surface_client;
1602 scoped_ptr<OutputSurface> parent_output_surface(FakeOutputSurface::Create3d(
1603 parent_context_owned.PassAs<TestWebGraphicsContext3D>()));
1604 CHECK(parent_output_surface->BindToClient(&parent_output_surface_client));
1606 scoped_ptr<ResourceProvider> parent_resource_provider(
1607 ResourceProvider::Create(parent_output_surface.get(),
1608 shared_bitmap_manager.get(),
1610 false,
1611 1));
1613 gfx::Size size(1, 1);
1614 ResourceFormat format = RGBA_8888;
1615 int child_texture_id = 1;
1616 int parent_texture_id = 2;
1618 size_t pixel_size = TextureSizeBytes(size, format);
1619 ASSERT_EQ(4U, pixel_size);
1621 ResourceProvider::ResourceId id = child_resource_provider->CreateResource(
1622 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
1624 // The new texture is created with GL_LINEAR.
1625 EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, child_texture_id))
1626 .Times(2); // Once to create and once to allocate.
1627 EXPECT_CALL(*child_context,
1628 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
1629 EXPECT_CALL(*child_context,
1630 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
1631 EXPECT_CALL(
1632 *child_context,
1633 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
1634 EXPECT_CALL(
1635 *child_context,
1636 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
1637 EXPECT_CALL(*child_context,
1638 texParameteri(GL_TEXTURE_2D,
1639 GL_TEXTURE_POOL_CHROMIUM,
1640 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM));
1641 child_resource_provider->AllocateForTesting(id);
1642 Mock::VerifyAndClearExpectations(child_context);
1644 uint8_t data[4] = { 1, 2, 3, 4 };
1645 gfx::Rect rect(size);
1647 EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, child_texture_id));
1648 child_resource_provider->SetPixels(id, data, rect, rect, gfx::Vector2d());
1649 Mock::VerifyAndClearExpectations(child_context);
1651 // The texture is set to |child_filter| in the child.
1652 EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, child_texture_id));
1653 if (child_filter != GL_LINEAR) {
1654 EXPECT_CALL(
1655 *child_context,
1656 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, child_filter));
1657 EXPECT_CALL(
1658 *child_context,
1659 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, child_filter));
1661 SetResourceFilter(child_resource_provider.get(), id, child_filter);
1662 Mock::VerifyAndClearExpectations(child_context);
1664 ReturnedResourceArray returned_to_child;
1665 int child_id = parent_resource_provider->CreateChild(
1666 GetReturnCallback(&returned_to_child));
1668 // Transfer some resource to the parent.
1669 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1670 resource_ids_to_transfer.push_back(id);
1671 TransferableResourceArray list;
1673 EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, child_texture_id));
1674 EXPECT_CALL(*child_context,
1675 produceTextureCHROMIUM(GL_TEXTURE_2D, _));
1676 EXPECT_CALL(*child_context, insertSyncPoint());
1677 child_resource_provider->PrepareSendToParent(resource_ids_to_transfer,
1678 &list);
1679 Mock::VerifyAndClearExpectations(child_context);
1681 ASSERT_EQ(1u, list.size());
1682 EXPECT_EQ(static_cast<unsigned>(child_filter), list[0].filter);
1684 EXPECT_CALL(*parent_context,
1685 bindTexture(GL_TEXTURE_2D, parent_texture_id));
1686 EXPECT_CALL(*parent_context, consumeTextureCHROMIUM(GL_TEXTURE_2D, _));
1687 parent_resource_provider->ReceiveFromChild(child_id, list);
1689 ResourceProvider::ScopedReadLockGL lock(parent_resource_provider.get(),
1690 list[0].id);
1692 Mock::VerifyAndClearExpectations(parent_context);
1694 parent_resource_provider->DeclareUsedResourcesFromChild(
1695 child_id, resource_ids_to_transfer);
1696 Mock::VerifyAndClearExpectations(parent_context);
1698 ResourceProvider::ResourceIdMap resource_map =
1699 parent_resource_provider->GetChildToParentMap(child_id);
1700 ResourceProvider::ResourceId mapped_id = resource_map[id];
1701 EXPECT_NE(0u, mapped_id);
1703 // The texture is set to |parent_filter| in the parent.
1704 EXPECT_CALL(*parent_context, bindTexture(GL_TEXTURE_2D, parent_texture_id));
1705 EXPECT_CALL(
1706 *parent_context,
1707 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, parent_filter));
1708 EXPECT_CALL(
1709 *parent_context,
1710 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, parent_filter));
1711 SetResourceFilter(parent_resource_provider.get(), mapped_id, parent_filter);
1712 Mock::VerifyAndClearExpectations(parent_context);
1714 // The texture should be reset to |child_filter| in the parent when it is
1715 // returned, since that is how it was received.
1716 EXPECT_CALL(*parent_context, bindTexture(GL_TEXTURE_2D, parent_texture_id));
1717 EXPECT_CALL(
1718 *parent_context,
1719 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, child_filter));
1720 EXPECT_CALL(
1721 *parent_context,
1722 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, child_filter));
1725 EXPECT_EQ(0u, returned_to_child.size());
1727 // Transfer resources back from the parent to the child. Set no resources
1728 // as being in use.
1729 ResourceProvider::ResourceIdArray no_resources;
1730 EXPECT_CALL(*parent_context, insertSyncPoint());
1731 parent_resource_provider->DeclareUsedResourcesFromChild(child_id,
1732 no_resources);
1733 Mock::VerifyAndClearExpectations(parent_context);
1735 ASSERT_EQ(1u, returned_to_child.size());
1736 child_resource_provider->ReceiveReturnsFromParent(returned_to_child);
1739 // The child remembers the texture filter is set to |child_filter|.
1740 EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, child_texture_id));
1741 SetResourceFilter(child_resource_provider.get(), id, child_filter);
1742 Mock::VerifyAndClearExpectations(child_context);
1746 TEST_P(ResourceProviderTest, TextureFilters_ChildNearestParentLinear) {
1747 if (GetParam() != ResourceProvider::GLTexture)
1748 return;
1749 ResourceProviderTestTextureFilters::RunTest(GL_NEAREST, GL_LINEAR);
1752 TEST_P(ResourceProviderTest, TextureFilters_ChildLinearParentNearest) {
1753 if (GetParam() != ResourceProvider::GLTexture)
1754 return;
1755 ResourceProviderTestTextureFilters::RunTest(GL_LINEAR, GL_NEAREST);
1758 TEST_P(ResourceProviderTest, TransferMailboxResources) {
1759 // Other mailbox transfers tested elsewhere.
1760 if (GetParam() != ResourceProvider::GLTexture)
1761 return;
1762 unsigned texture = context()->createTexture();
1763 context()->bindTexture(GL_TEXTURE_2D, texture);
1764 uint8_t data[4] = { 1, 2, 3, 4 };
1765 context()->texImage2D(
1766 GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &data);
1767 gpu::Mailbox mailbox;
1768 context()->genMailboxCHROMIUM(mailbox.name);
1769 context()->produceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
1770 uint32 sync_point = context()->insertSyncPoint();
1772 // All the logic below assumes that the sync points are all positive.
1773 EXPECT_LT(0u, sync_point);
1775 uint32 release_sync_point = 0;
1776 bool lost_resource = false;
1777 ReleaseCallback callback =
1778 base::Bind(ReleaseTextureMailbox, &release_sync_point, &lost_resource);
1779 ResourceProvider::ResourceId resource =
1780 resource_provider_->CreateResourceFromTextureMailbox(
1781 TextureMailbox(mailbox, GL_TEXTURE_2D, sync_point),
1782 SingleReleaseCallback::Create(callback));
1783 EXPECT_EQ(1u, context()->NumTextures());
1784 EXPECT_EQ(0u, release_sync_point);
1786 // Transfer the resource, expect the sync points to be consistent.
1787 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1788 resource_ids_to_transfer.push_back(resource);
1789 TransferableResourceArray list;
1790 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
1791 ASSERT_EQ(1u, list.size());
1792 EXPECT_LE(sync_point, list[0].mailbox_holder.sync_point);
1793 EXPECT_EQ(0,
1794 memcmp(mailbox.name,
1795 list[0].mailbox_holder.mailbox.name,
1796 sizeof(mailbox.name)));
1797 EXPECT_EQ(0u, release_sync_point);
1799 context()->waitSyncPoint(list[0].mailbox_holder.sync_point);
1800 unsigned other_texture = context()->createTexture();
1801 context()->bindTexture(GL_TEXTURE_2D, other_texture);
1802 context()->consumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
1803 uint8_t test_data[4] = { 0 };
1804 context()->GetPixels(
1805 gfx::Size(1, 1), RGBA_8888, test_data);
1806 EXPECT_EQ(0, memcmp(data, test_data, sizeof(data)));
1807 context()->produceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
1808 context()->deleteTexture(other_texture);
1809 list[0].mailbox_holder.sync_point = context()->insertSyncPoint();
1810 EXPECT_LT(0u, list[0].mailbox_holder.sync_point);
1812 // Receive the resource, then delete it, expect the sync points to be
1813 // consistent.
1814 ReturnedResourceArray returned;
1815 TransferableResource::ReturnResources(list, &returned);
1816 resource_provider_->ReceiveReturnsFromParent(returned);
1817 EXPECT_EQ(1u, context()->NumTextures());
1818 EXPECT_EQ(0u, release_sync_point);
1820 resource_provider_->DeleteResource(resource);
1821 EXPECT_LE(list[0].mailbox_holder.sync_point, release_sync_point);
1822 EXPECT_FALSE(lost_resource);
1825 // We're going to do the same thing as above, but testing the case where we
1826 // delete the resource before we receive it back.
1827 sync_point = release_sync_point;
1828 EXPECT_LT(0u, sync_point);
1829 release_sync_point = 0;
1830 resource = resource_provider_->CreateResourceFromTextureMailbox(
1831 TextureMailbox(mailbox, GL_TEXTURE_2D, sync_point),
1832 SingleReleaseCallback::Create(callback));
1833 EXPECT_EQ(1u, context()->NumTextures());
1834 EXPECT_EQ(0u, release_sync_point);
1836 // Transfer the resource, expect the sync points to be consistent.
1837 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1838 resource_ids_to_transfer.push_back(resource);
1839 TransferableResourceArray list;
1840 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
1841 ASSERT_EQ(1u, list.size());
1842 EXPECT_LE(sync_point, list[0].mailbox_holder.sync_point);
1843 EXPECT_EQ(0,
1844 memcmp(mailbox.name,
1845 list[0].mailbox_holder.mailbox.name,
1846 sizeof(mailbox.name)));
1847 EXPECT_EQ(0u, release_sync_point);
1849 context()->waitSyncPoint(list[0].mailbox_holder.sync_point);
1850 unsigned other_texture = context()->createTexture();
1851 context()->bindTexture(GL_TEXTURE_2D, other_texture);
1852 context()->consumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
1853 uint8_t test_data[4] = { 0 };
1854 context()->GetPixels(
1855 gfx::Size(1, 1), RGBA_8888, test_data);
1856 EXPECT_EQ(0, memcmp(data, test_data, sizeof(data)));
1857 context()->produceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
1858 context()->deleteTexture(other_texture);
1859 list[0].mailbox_holder.sync_point = context()->insertSyncPoint();
1860 EXPECT_LT(0u, list[0].mailbox_holder.sync_point);
1862 // Delete the resource, which shouldn't do anything.
1863 resource_provider_->DeleteResource(resource);
1864 EXPECT_EQ(1u, context()->NumTextures());
1865 EXPECT_EQ(0u, release_sync_point);
1867 // Then receive the resource which should release the mailbox, expect the
1868 // sync points to be consistent.
1869 ReturnedResourceArray returned;
1870 TransferableResource::ReturnResources(list, &returned);
1871 resource_provider_->ReceiveReturnsFromParent(returned);
1872 EXPECT_LE(list[0].mailbox_holder.sync_point, release_sync_point);
1873 EXPECT_FALSE(lost_resource);
1876 context()->waitSyncPoint(release_sync_point);
1877 context()->bindTexture(GL_TEXTURE_2D, texture);
1878 context()->consumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
1879 context()->deleteTexture(texture);
1882 TEST_P(ResourceProviderTest, LostResourceInParent) {
1883 gfx::Size size(1, 1);
1884 ResourceFormat format = RGBA_8888;
1885 ResourceProvider::ResourceId resource =
1886 child_resource_provider_->CreateResource(
1887 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
1888 child_resource_provider_->AllocateForTesting(resource);
1889 // Expect a GL resource to be lost.
1890 bool should_lose_resource = GetParam() == ResourceProvider::GLTexture;
1892 ReturnedResourceArray returned_to_child;
1893 int child_id =
1894 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1896 // Transfer the resource to the parent.
1897 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1898 resource_ids_to_transfer.push_back(resource);
1899 TransferableResourceArray list;
1900 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1901 &list);
1902 EXPECT_EQ(1u, list.size());
1904 resource_provider_->ReceiveFromChild(child_id, list);
1905 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1906 resource_ids_to_transfer);
1909 // Lose the output surface in the parent.
1910 resource_provider_->DidLoseOutputSurface();
1913 EXPECT_EQ(0u, returned_to_child.size());
1915 // Transfer resources back from the parent to the child. Set no resources as
1916 // being in use.
1917 ResourceProvider::ResourceIdArray no_resources;
1918 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
1920 // Expect a GL resource to be lost.
1921 ASSERT_EQ(1u, returned_to_child.size());
1922 EXPECT_EQ(should_lose_resource, returned_to_child[0].lost);
1923 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
1924 returned_to_child.clear();
1927 // A GL resource should be lost.
1928 EXPECT_EQ(should_lose_resource, child_resource_provider_->IsLost(resource));
1930 // Lost resources stay in use in the parent forever.
1931 EXPECT_EQ(should_lose_resource,
1932 child_resource_provider_->InUseByConsumer(resource));
1935 TEST_P(ResourceProviderTest, LostResourceInGrandParent) {
1936 gfx::Size size(1, 1);
1937 ResourceFormat format = RGBA_8888;
1938 ResourceProvider::ResourceId resource =
1939 child_resource_provider_->CreateResource(
1940 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
1941 child_resource_provider_->AllocateForTesting(resource);
1943 ReturnedResourceArray returned_to_child;
1944 int child_id =
1945 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1947 // Transfer the resource to the parent.
1948 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1949 resource_ids_to_transfer.push_back(resource);
1950 TransferableResourceArray list;
1951 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1952 &list);
1953 EXPECT_EQ(1u, list.size());
1955 resource_provider_->ReceiveFromChild(child_id, list);
1956 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1957 resource_ids_to_transfer);
1961 ResourceProvider::ResourceIdMap resource_map =
1962 resource_provider_->GetChildToParentMap(child_id);
1963 ResourceProvider::ResourceId parent_resource = resource_map[resource];
1964 EXPECT_NE(0u, parent_resource);
1966 // Transfer to a grandparent.
1967 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1968 resource_ids_to_transfer.push_back(parent_resource);
1969 TransferableResourceArray list;
1970 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
1972 // Receive back a lost resource from the grandparent.
1973 EXPECT_EQ(1u, list.size());
1974 EXPECT_EQ(parent_resource, list[0].id);
1975 ReturnedResourceArray returned;
1976 TransferableResource::ReturnResources(list, &returned);
1977 EXPECT_EQ(1u, returned.size());
1978 EXPECT_EQ(parent_resource, returned[0].id);
1979 returned[0].lost = true;
1980 resource_provider_->ReceiveReturnsFromParent(returned);
1982 // The resource should be lost.
1983 EXPECT_TRUE(resource_provider_->IsLost(parent_resource));
1985 // Lost resources stay in use in the parent forever.
1986 EXPECT_TRUE(resource_provider_->InUseByConsumer(parent_resource));
1990 EXPECT_EQ(0u, returned_to_child.size());
1992 // Transfer resources back from the parent to the child. Set no resources as
1993 // being in use.
1994 ResourceProvider::ResourceIdArray no_resources;
1995 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
1997 // Expect the resource to be lost.
1998 ASSERT_EQ(1u, returned_to_child.size());
1999 EXPECT_TRUE(returned_to_child[0].lost);
2000 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
2001 returned_to_child.clear();
2004 // The resource should be lost.
2005 EXPECT_TRUE(child_resource_provider_->IsLost(resource));
2007 // Lost resources stay in use in the parent forever.
2008 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(resource));
2011 TEST_P(ResourceProviderTest, LostMailboxInParent) {
2012 uint32 release_sync_point = 0;
2013 bool lost_resource = false;
2014 bool release_called = false;
2015 uint32 sync_point = 0;
2016 ResourceProvider::ResourceId resource = CreateChildMailbox(
2017 &release_sync_point, &lost_resource, &release_called, &sync_point);
2019 ReturnedResourceArray returned_to_child;
2020 int child_id =
2021 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
2023 // Transfer the resource to the parent.
2024 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2025 resource_ids_to_transfer.push_back(resource);
2026 TransferableResourceArray list;
2027 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
2028 &list);
2029 EXPECT_EQ(1u, list.size());
2031 resource_provider_->ReceiveFromChild(child_id, list);
2032 resource_provider_->DeclareUsedResourcesFromChild(child_id,
2033 resource_ids_to_transfer);
2036 // Lose the output surface in the parent.
2037 resource_provider_->DidLoseOutputSurface();
2040 EXPECT_EQ(0u, returned_to_child.size());
2042 // Transfer resources back from the parent to the child. Set no resources as
2043 // being in use.
2044 ResourceProvider::ResourceIdArray no_resources;
2045 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
2047 ASSERT_EQ(1u, returned_to_child.size());
2048 // Losing an output surface only loses hardware resources.
2049 EXPECT_EQ(returned_to_child[0].lost,
2050 GetParam() == ResourceProvider::GLTexture);
2051 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
2052 returned_to_child.clear();
2055 // Delete the resource in the child. Expect the resource to be lost if it's
2056 // a GL texture.
2057 child_resource_provider_->DeleteResource(resource);
2058 EXPECT_EQ(lost_resource, GetParam() == ResourceProvider::GLTexture);
2061 TEST_P(ResourceProviderTest, LostMailboxInGrandParent) {
2062 uint32 release_sync_point = 0;
2063 bool lost_resource = false;
2064 bool release_called = false;
2065 uint32 sync_point = 0;
2066 ResourceProvider::ResourceId resource = CreateChildMailbox(
2067 &release_sync_point, &lost_resource, &release_called, &sync_point);
2069 ReturnedResourceArray returned_to_child;
2070 int child_id =
2071 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
2073 // Transfer the resource to the parent.
2074 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2075 resource_ids_to_transfer.push_back(resource);
2076 TransferableResourceArray list;
2077 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
2078 &list);
2079 EXPECT_EQ(1u, list.size());
2081 resource_provider_->ReceiveFromChild(child_id, list);
2082 resource_provider_->DeclareUsedResourcesFromChild(child_id,
2083 resource_ids_to_transfer);
2087 ResourceProvider::ResourceIdMap resource_map =
2088 resource_provider_->GetChildToParentMap(child_id);
2089 ResourceProvider::ResourceId parent_resource = resource_map[resource];
2090 EXPECT_NE(0u, parent_resource);
2092 // Transfer to a grandparent.
2093 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2094 resource_ids_to_transfer.push_back(parent_resource);
2095 TransferableResourceArray list;
2096 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
2098 // Receive back a lost resource from the grandparent.
2099 EXPECT_EQ(1u, list.size());
2100 EXPECT_EQ(parent_resource, list[0].id);
2101 ReturnedResourceArray returned;
2102 TransferableResource::ReturnResources(list, &returned);
2103 EXPECT_EQ(1u, returned.size());
2104 EXPECT_EQ(parent_resource, returned[0].id);
2105 returned[0].lost = true;
2106 resource_provider_->ReceiveReturnsFromParent(returned);
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 // Expect the resource to be lost.
2118 ASSERT_EQ(1u, returned_to_child.size());
2119 EXPECT_TRUE(returned_to_child[0].lost);
2120 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
2121 returned_to_child.clear();
2124 // Delete the resource in the child. Expect the resource to be lost.
2125 child_resource_provider_->DeleteResource(resource);
2126 EXPECT_TRUE(lost_resource);
2129 TEST_P(ResourceProviderTest, Shutdown) {
2130 uint32 release_sync_point = 0;
2131 bool lost_resource = false;
2132 bool release_called = false;
2133 uint32 sync_point = 0;
2134 CreateChildMailbox(
2135 &release_sync_point, &lost_resource, &release_called, &sync_point);
2137 EXPECT_EQ(0u, release_sync_point);
2138 EXPECT_FALSE(lost_resource);
2140 child_resource_provider_.reset();
2142 if (GetParam() == ResourceProvider::GLTexture) {
2143 EXPECT_LE(sync_point, release_sync_point);
2145 EXPECT_TRUE(release_called);
2146 EXPECT_FALSE(lost_resource);
2149 TEST_P(ResourceProviderTest, ShutdownWithExportedResource) {
2150 uint32 release_sync_point = 0;
2151 bool lost_resource = false;
2152 bool release_called = false;
2153 uint32 sync_point = 0;
2154 ResourceProvider::ResourceId resource = CreateChildMailbox(
2155 &release_sync_point, &lost_resource, &release_called, &sync_point);
2157 // Transfer the resource, so we can't release it properly on shutdown.
2158 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2159 resource_ids_to_transfer.push_back(resource);
2160 TransferableResourceArray list;
2161 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
2162 &list);
2164 EXPECT_EQ(0u, release_sync_point);
2165 EXPECT_FALSE(lost_resource);
2167 child_resource_provider_.reset();
2169 // Since the resource is in the parent, the child considers it lost.
2170 EXPECT_EQ(0u, release_sync_point);
2171 EXPECT_TRUE(lost_resource);
2174 TEST_P(ResourceProviderTest, LostContext) {
2175 // TextureMailbox callbacks only exist for GL textures for now.
2176 if (GetParam() != ResourceProvider::GLTexture)
2177 return;
2178 unsigned texture = context()->createTexture();
2179 context()->bindTexture(GL_TEXTURE_2D, texture);
2180 gpu::Mailbox mailbox;
2181 context()->genMailboxCHROMIUM(mailbox.name);
2182 context()->produceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
2183 uint32 sync_point = context()->insertSyncPoint();
2185 EXPECT_LT(0u, sync_point);
2187 uint32 release_sync_point = 0;
2188 bool lost_resource = false;
2189 scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create(
2190 base::Bind(ReleaseTextureMailbox, &release_sync_point, &lost_resource));
2191 resource_provider_->CreateResourceFromTextureMailbox(
2192 TextureMailbox(mailbox, GL_TEXTURE_2D, sync_point), callback.Pass());
2194 EXPECT_EQ(0u, release_sync_point);
2195 EXPECT_FALSE(lost_resource);
2197 resource_provider_->DidLoseOutputSurface();
2198 resource_provider_.reset();
2200 EXPECT_LE(sync_point, release_sync_point);
2201 EXPECT_TRUE(lost_resource);
2204 TEST_P(ResourceProviderTest, ScopedSampler) {
2205 // Sampling is only supported for GL textures.
2206 if (GetParam() != ResourceProvider::GLTexture)
2207 return;
2209 scoped_ptr<TextureStateTrackingContext> context_owned(
2210 new TextureStateTrackingContext);
2211 TextureStateTrackingContext* context = context_owned.get();
2213 FakeOutputSurfaceClient output_surface_client;
2214 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
2215 context_owned.PassAs<TestWebGraphicsContext3D>()));
2216 CHECK(output_surface->BindToClient(&output_surface_client));
2218 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
2219 output_surface.get(), shared_bitmap_manager_.get(), 0, false, 1));
2221 gfx::Size size(1, 1);
2222 ResourceFormat format = RGBA_8888;
2223 int texture_id = 1;
2225 ResourceProvider::ResourceId id = resource_provider->CreateResource(
2226 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
2228 // Check that the texture gets created with the right sampler settings.
2229 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id))
2230 .Times(2); // Once to create and once to allocate.
2231 EXPECT_CALL(*context,
2232 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
2233 EXPECT_CALL(*context,
2234 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
2235 EXPECT_CALL(
2236 *context,
2237 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
2238 EXPECT_CALL(
2239 *context,
2240 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
2241 EXPECT_CALL(*context,
2242 texParameteri(GL_TEXTURE_2D,
2243 GL_TEXTURE_POOL_CHROMIUM,
2244 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM));
2246 resource_provider->AllocateForTesting(id);
2247 Mock::VerifyAndClearExpectations(context);
2249 // Creating a sampler with the default filter should not change any texture
2250 // parameters.
2252 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
2253 ResourceProvider::ScopedSamplerGL sampler(
2254 resource_provider.get(), id, GL_TEXTURE_2D, GL_LINEAR);
2255 Mock::VerifyAndClearExpectations(context);
2258 // Using a different filter should be reflected in the texture parameters.
2260 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
2261 EXPECT_CALL(
2262 *context,
2263 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
2264 EXPECT_CALL(
2265 *context,
2266 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
2267 ResourceProvider::ScopedSamplerGL sampler(
2268 resource_provider.get(), id, GL_TEXTURE_2D, GL_NEAREST);
2269 Mock::VerifyAndClearExpectations(context);
2272 // Test resetting to the default filter.
2274 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
2275 EXPECT_CALL(*context,
2276 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
2277 EXPECT_CALL(*context,
2278 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
2279 ResourceProvider::ScopedSamplerGL sampler(
2280 resource_provider.get(), id, GL_TEXTURE_2D, GL_LINEAR);
2281 Mock::VerifyAndClearExpectations(context);
2285 TEST_P(ResourceProviderTest, ManagedResource) {
2286 // Sampling is only supported for GL textures.
2287 if (GetParam() != ResourceProvider::GLTexture)
2288 return;
2290 scoped_ptr<TextureStateTrackingContext> context_owned(
2291 new TextureStateTrackingContext);
2292 TextureStateTrackingContext* context = context_owned.get();
2294 FakeOutputSurfaceClient output_surface_client;
2295 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
2296 context_owned.PassAs<TestWebGraphicsContext3D>()));
2297 CHECK(output_surface->BindToClient(&output_surface_client));
2299 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
2300 output_surface.get(), shared_bitmap_manager_.get(), 0, false, 1));
2302 gfx::Size size(1, 1);
2303 ResourceFormat format = RGBA_8888;
2304 int texture_id = 1;
2306 // Check that the texture gets created with the right sampler settings.
2307 ResourceProvider::ResourceId id = resource_provider->CreateManagedResource(
2308 size,
2309 GL_TEXTURE_2D,
2310 GL_CLAMP_TO_EDGE,
2311 ResourceProvider::TextureUsageAny,
2312 format);
2313 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
2314 EXPECT_CALL(*context,
2315 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
2316 EXPECT_CALL(*context,
2317 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
2318 EXPECT_CALL(
2319 *context,
2320 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
2321 EXPECT_CALL(
2322 *context,
2323 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
2324 EXPECT_CALL(*context,
2325 texParameteri(GL_TEXTURE_2D,
2326 GL_TEXTURE_POOL_CHROMIUM,
2327 GL_TEXTURE_POOL_MANAGED_CHROMIUM));
2328 resource_provider->CreateForTesting(id);
2329 EXPECT_NE(0u, id);
2331 Mock::VerifyAndClearExpectations(context);
2334 TEST_P(ResourceProviderTest, TextureWrapMode) {
2335 // Sampling is only supported for GL textures.
2336 if (GetParam() != ResourceProvider::GLTexture)
2337 return;
2339 scoped_ptr<TextureStateTrackingContext> context_owned(
2340 new TextureStateTrackingContext);
2341 TextureStateTrackingContext* context = context_owned.get();
2343 FakeOutputSurfaceClient output_surface_client;
2344 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
2345 context_owned.PassAs<TestWebGraphicsContext3D>()));
2346 CHECK(output_surface->BindToClient(&output_surface_client));
2348 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
2349 output_surface.get(), shared_bitmap_manager_.get(), 0, false, 1));
2351 gfx::Size size(1, 1);
2352 ResourceFormat format = RGBA_8888;
2353 GLenum texture_pool = GL_TEXTURE_POOL_UNMANAGED_CHROMIUM;
2355 for (int texture_id = 1; texture_id <= 2; ++texture_id) {
2356 GLint wrap_mode = texture_id == 1 ? GL_CLAMP_TO_EDGE : GL_REPEAT;
2357 // Check that the texture gets created with the right sampler settings.
2358 ResourceProvider::ResourceId id =
2359 resource_provider->CreateGLTexture(size,
2360 GL_TEXTURE_2D,
2361 texture_pool,
2362 wrap_mode,
2363 ResourceProvider::TextureUsageAny,
2364 format);
2365 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
2366 EXPECT_CALL(*context,
2367 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
2368 EXPECT_CALL(*context,
2369 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
2370 EXPECT_CALL(
2371 *context,
2372 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap_mode));
2373 EXPECT_CALL(
2374 *context,
2375 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap_mode));
2376 EXPECT_CALL(*context,
2377 texParameteri(GL_TEXTURE_2D,
2378 GL_TEXTURE_POOL_CHROMIUM,
2379 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM));
2380 resource_provider->CreateForTesting(id);
2381 EXPECT_NE(0u, id);
2383 Mock::VerifyAndClearExpectations(context);
2387 TEST_P(ResourceProviderTest, TextureMailbox_SharedMemory) {
2388 if (GetParam() != ResourceProvider::Bitmap)
2389 return;
2391 gfx::Size size(64, 64);
2392 const uint32_t kBadBeef = 0xbadbeef;
2393 scoped_ptr<base::SharedMemory> shared_memory(
2394 CreateAndFillSharedMemory(size, kBadBeef));
2396 FakeOutputSurfaceClient output_surface_client;
2397 scoped_ptr<OutputSurface> output_surface(
2398 FakeOutputSurface::CreateSoftware(make_scoped_ptr(
2399 new SoftwareOutputDevice)));
2400 CHECK(output_surface->BindToClient(&output_surface_client));
2402 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
2403 output_surface.get(), shared_bitmap_manager_.get(), 0, false, 1));
2405 scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create(
2406 base::Bind(&EmptyReleaseCallback));
2407 TextureMailbox mailbox(shared_memory.get(), size);
2409 ResourceProvider::ResourceId id =
2410 resource_provider->CreateResourceFromTextureMailbox(
2411 mailbox, callback.Pass());
2412 EXPECT_NE(0u, id);
2415 ResourceProvider::ScopedReadLockSoftware lock(resource_provider.get(), id);
2416 const SkBitmap* sk_bitmap = lock.sk_bitmap();
2417 EXPECT_EQ(sk_bitmap->width(), size.width());
2418 EXPECT_EQ(sk_bitmap->height(), size.height());
2419 EXPECT_EQ(*sk_bitmap->getAddr32(16, 16), kBadBeef);
2423 TEST_P(ResourceProviderTest, TextureMailbox_GLTexture2D) {
2424 // Mailboxing is only supported for GL textures.
2425 if (GetParam() != ResourceProvider::GLTexture)
2426 return;
2428 scoped_ptr<TextureStateTrackingContext> context_owned(
2429 new TextureStateTrackingContext);
2430 TextureStateTrackingContext* context = context_owned.get();
2432 FakeOutputSurfaceClient output_surface_client;
2433 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
2434 context_owned.PassAs<TestWebGraphicsContext3D>()));
2435 CHECK(output_surface->BindToClient(&output_surface_client));
2437 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
2438 output_surface.get(), shared_bitmap_manager_.get(), 0, false, 1));
2440 unsigned texture_id = 1;
2441 uint32 sync_point = 30;
2442 unsigned target = GL_TEXTURE_2D;
2444 EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
2445 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
2446 EXPECT_CALL(*context, insertSyncPoint()).Times(0);
2447 EXPECT_CALL(*context, produceTextureCHROMIUM(_, _)).Times(0);
2448 EXPECT_CALL(*context, consumeTextureCHROMIUM(_, _)).Times(0);
2450 gpu::Mailbox gpu_mailbox;
2451 memcpy(gpu_mailbox.name, "Hello world", strlen("Hello world") + 1);
2452 scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create(
2453 base::Bind(&EmptyReleaseCallback));
2455 TextureMailbox mailbox(gpu_mailbox, target, sync_point);
2457 ResourceProvider::ResourceId id =
2458 resource_provider->CreateResourceFromTextureMailbox(
2459 mailbox, callback.Pass());
2460 EXPECT_NE(0u, id);
2462 Mock::VerifyAndClearExpectations(context);
2465 // Using the texture does a consume of the mailbox.
2466 EXPECT_CALL(*context, bindTexture(target, texture_id));
2467 EXPECT_CALL(*context, waitSyncPoint(sync_point));
2468 EXPECT_CALL(*context, consumeTextureCHROMIUM(target, _));
2470 EXPECT_CALL(*context, insertSyncPoint()).Times(0);
2471 EXPECT_CALL(*context, produceTextureCHROMIUM(_, _)).Times(0);
2473 ResourceProvider::ScopedReadLockGL lock(resource_provider.get(), id);
2474 Mock::VerifyAndClearExpectations(context);
2476 // When done with it, a sync point should be inserted, but no produce is
2477 // necessary.
2478 EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
2479 EXPECT_CALL(*context, insertSyncPoint());
2480 EXPECT_CALL(*context, produceTextureCHROMIUM(_, _)).Times(0);
2482 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
2483 EXPECT_CALL(*context, consumeTextureCHROMIUM(_, _)).Times(0);
2487 TEST_P(ResourceProviderTest, TextureMailbox_GLTextureExternalOES) {
2488 // Mailboxing is only supported for GL textures.
2489 if (GetParam() != ResourceProvider::GLTexture)
2490 return;
2492 scoped_ptr<TextureStateTrackingContext> context_owned(
2493 new TextureStateTrackingContext);
2494 TextureStateTrackingContext* context = context_owned.get();
2496 FakeOutputSurfaceClient output_surface_client;
2497 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
2498 context_owned.PassAs<TestWebGraphicsContext3D>()));
2499 CHECK(output_surface->BindToClient(&output_surface_client));
2501 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
2502 output_surface.get(), shared_bitmap_manager_.get(), 0, false, 1));
2504 unsigned texture_id = 1;
2505 uint32 sync_point = 30;
2506 unsigned target = GL_TEXTURE_EXTERNAL_OES;
2508 EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
2509 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
2510 EXPECT_CALL(*context, insertSyncPoint()).Times(0);
2511 EXPECT_CALL(*context, produceTextureCHROMIUM(_, _)).Times(0);
2512 EXPECT_CALL(*context, consumeTextureCHROMIUM(_, _)).Times(0);
2514 gpu::Mailbox gpu_mailbox;
2515 memcpy(gpu_mailbox.name, "Hello world", strlen("Hello world") + 1);
2516 scoped_ptr<SingleReleaseCallback> callback = SingleReleaseCallback::Create(
2517 base::Bind(&EmptyReleaseCallback));
2519 TextureMailbox mailbox(gpu_mailbox, target, sync_point);
2521 ResourceProvider::ResourceId id =
2522 resource_provider->CreateResourceFromTextureMailbox(
2523 mailbox, callback.Pass());
2524 EXPECT_NE(0u, id);
2526 Mock::VerifyAndClearExpectations(context);
2529 // Using the texture does a consume of the mailbox.
2530 EXPECT_CALL(*context, bindTexture(target, texture_id));
2531 EXPECT_CALL(*context, waitSyncPoint(sync_point));
2532 EXPECT_CALL(*context, consumeTextureCHROMIUM(target, _));
2534 EXPECT_CALL(*context, insertSyncPoint()).Times(0);
2535 EXPECT_CALL(*context, produceTextureCHROMIUM(_, _)).Times(0);
2537 ResourceProvider::ScopedReadLockGL lock(resource_provider.get(), id);
2538 Mock::VerifyAndClearExpectations(context);
2540 // When done with it, a sync point should be inserted, but no produce is
2541 // necessary.
2542 EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
2543 EXPECT_CALL(*context, insertSyncPoint());
2544 EXPECT_CALL(*context, produceTextureCHROMIUM(_, _)).Times(0);
2546 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
2547 EXPECT_CALL(*context, consumeTextureCHROMIUM(_, _)).Times(0);
2551 class AllocationTrackingContext3D : public TestWebGraphicsContext3D {
2552 public:
2553 MOCK_METHOD0(NextTextureId, GLuint());
2554 MOCK_METHOD1(RetireTextureId, void(GLuint id));
2555 MOCK_METHOD2(bindTexture, void(GLenum target, GLuint texture));
2556 MOCK_METHOD5(texStorage2DEXT,
2557 void(GLenum target,
2558 GLint levels,
2559 GLuint internalformat,
2560 GLint width,
2561 GLint height));
2562 MOCK_METHOD9(texImage2D,
2563 void(GLenum target,
2564 GLint level,
2565 GLenum internalformat,
2566 GLsizei width,
2567 GLsizei height,
2568 GLint border,
2569 GLenum format,
2570 GLenum type,
2571 const void* pixels));
2572 MOCK_METHOD9(texSubImage2D,
2573 void(GLenum target,
2574 GLint level,
2575 GLint xoffset,
2576 GLint yoffset,
2577 GLsizei width,
2578 GLsizei height,
2579 GLenum format,
2580 GLenum type,
2581 const void* pixels));
2582 MOCK_METHOD9(asyncTexImage2DCHROMIUM,
2583 void(GLenum target,
2584 GLint level,
2585 GLenum internalformat,
2586 GLsizei width,
2587 GLsizei height,
2588 GLint border,
2589 GLenum format,
2590 GLenum type,
2591 const void* pixels));
2592 MOCK_METHOD9(asyncTexSubImage2DCHROMIUM,
2593 void(GLenum target,
2594 GLint level,
2595 GLint xoffset,
2596 GLint yoffset,
2597 GLsizei width,
2598 GLsizei height,
2599 GLenum format,
2600 GLenum type,
2601 const void* pixels));
2602 MOCK_METHOD8(compressedTexImage2D,
2603 void(GLenum target,
2604 GLint level,
2605 GLenum internalformat,
2606 GLsizei width,
2607 GLsizei height,
2608 GLint border,
2609 GLsizei image_size,
2610 const void* data));
2611 MOCK_METHOD1(waitAsyncTexImage2DCHROMIUM, void(GLenum));
2612 MOCK_METHOD3(createImageCHROMIUM, GLuint(GLsizei, GLsizei, GLenum));
2613 MOCK_METHOD1(destroyImageCHROMIUM, void(GLuint));
2614 MOCK_METHOD2(mapImageCHROMIUM, void*(GLuint, GLenum));
2615 MOCK_METHOD3(getImageParameterivCHROMIUM, void(GLuint, GLenum, GLint*));
2616 MOCK_METHOD1(unmapImageCHROMIUM, void(GLuint));
2617 MOCK_METHOD2(bindTexImage2DCHROMIUM, void(GLenum, GLint));
2618 MOCK_METHOD2(releaseTexImage2DCHROMIUM, void(GLenum, GLint));
2620 // We're mocking bindTexture, so we override
2621 // TestWebGraphicsContext3D::texParameteri to avoid assertions related to the
2622 // currently bound texture.
2623 virtual void texParameteri(GLenum target, GLenum pname, GLint param) {}
2626 TEST_P(ResourceProviderTest, TextureAllocation) {
2627 // Only for GL textures.
2628 if (GetParam() != ResourceProvider::GLTexture)
2629 return;
2630 scoped_ptr<AllocationTrackingContext3D> context_owned(
2631 new StrictMock<AllocationTrackingContext3D>);
2632 AllocationTrackingContext3D* context = context_owned.get();
2634 FakeOutputSurfaceClient output_surface_client;
2635 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
2636 context_owned.PassAs<TestWebGraphicsContext3D>()));
2637 CHECK(output_surface->BindToClient(&output_surface_client));
2639 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
2640 output_surface.get(), shared_bitmap_manager_.get(), 0, false, 1));
2642 gfx::Size size(2, 2);
2643 gfx::Vector2d offset(0, 0);
2644 gfx::Rect rect(0, 0, 2, 2);
2645 ResourceFormat format = RGBA_8888;
2646 ResourceProvider::ResourceId id = 0;
2647 uint8_t pixels[16] = { 0 };
2648 int texture_id = 123;
2650 // Lazy allocation. Don't allocate when creating the resource.
2651 id = resource_provider->CreateResource(
2652 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
2654 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
2655 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(1);
2656 resource_provider->CreateForTesting(id);
2658 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
2659 resource_provider->DeleteResource(id);
2661 Mock::VerifyAndClearExpectations(context);
2663 // Do allocate when we set the pixels.
2664 id = resource_provider->CreateResource(
2665 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
2667 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
2668 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(3);
2669 EXPECT_CALL(*context, texImage2D(_, _, _, 2, 2, _, _, _, _)).Times(1);
2670 EXPECT_CALL(*context, texSubImage2D(_, _, _, _, 2, 2, _, _, _)).Times(1);
2671 resource_provider->SetPixels(id, pixels, rect, rect, offset);
2673 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
2674 resource_provider->DeleteResource(id);
2676 Mock::VerifyAndClearExpectations(context);
2678 // Same for async version.
2679 id = resource_provider->CreateResource(
2680 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
2681 resource_provider->AcquirePixelRasterBuffer(id);
2683 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
2684 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
2685 EXPECT_CALL(*context, asyncTexImage2DCHROMIUM(_, _, _, 2, 2, _, _, _, _))
2686 .Times(1);
2687 resource_provider->BeginSetPixels(id);
2688 ASSERT_TRUE(resource_provider->DidSetPixelsComplete(id));
2690 resource_provider->ReleasePixelRasterBuffer(id);
2692 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
2693 resource_provider->DeleteResource(id);
2695 Mock::VerifyAndClearExpectations(context);
2698 TEST_P(ResourceProviderTest, TextureAllocationStorageUsageAny) {
2699 // Only for GL textures.
2700 if (GetParam() != ResourceProvider::GLTexture)
2701 return;
2702 scoped_ptr<AllocationTrackingContext3D> context_owned(
2703 new StrictMock<AllocationTrackingContext3D>);
2704 AllocationTrackingContext3D* context = context_owned.get();
2705 context->set_support_texture_storage(true);
2707 FakeOutputSurfaceClient output_surface_client;
2708 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
2709 context_owned.PassAs<TestWebGraphicsContext3D>()));
2710 CHECK(output_surface->BindToClient(&output_surface_client));
2712 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
2713 output_surface.get(), shared_bitmap_manager_.get(), 0, false, 1));
2715 gfx::Size size(2, 2);
2716 ResourceFormat format = RGBA_8888;
2717 ResourceProvider::ResourceId id = 0;
2718 int texture_id = 123;
2720 // Lazy allocation. Don't allocate when creating the resource.
2721 id = resource_provider->CreateResource(
2722 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
2724 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
2725 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
2726 EXPECT_CALL(*context, texStorage2DEXT(_, _, _, 2, 2)).Times(1);
2727 resource_provider->AllocateForTesting(id);
2729 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
2730 resource_provider->DeleteResource(id);
2732 Mock::VerifyAndClearExpectations(context);
2735 TEST_P(ResourceProviderTest, TextureAllocationStorageUsageFramebuffer) {
2736 // Only for GL textures.
2737 if (GetParam() != ResourceProvider::GLTexture)
2738 return;
2739 scoped_ptr<AllocationTrackingContext3D> context_owned(
2740 new StrictMock<AllocationTrackingContext3D>);
2741 AllocationTrackingContext3D* context = context_owned.get();
2742 context->set_support_texture_storage(true);
2744 FakeOutputSurfaceClient output_surface_client;
2745 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
2746 context_owned.PassAs<TestWebGraphicsContext3D>()));
2747 CHECK(output_surface->BindToClient(&output_surface_client));
2749 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
2750 output_surface.get(), shared_bitmap_manager_.get(), 0, false, 1));
2752 gfx::Size size(2, 2);
2753 ResourceFormat format = RGBA_8888;
2754 ResourceProvider::ResourceId id = 0;
2755 int texture_id = 123;
2757 // Lazy allocation. Don't allocate when creating the resource.
2758 id = resource_provider->CreateResource(
2759 size,
2760 GL_CLAMP_TO_EDGE,
2761 ResourceProvider::TextureUsageFramebuffer,
2762 format);
2764 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
2765 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
2766 EXPECT_CALL(*context, texImage2D(_, _, _, 2, 2, _, _, _, _)).Times(1);
2767 resource_provider->AllocateForTesting(id);
2769 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
2770 resource_provider->DeleteResource(id);
2772 Mock::VerifyAndClearExpectations(context);
2775 TEST_P(ResourceProviderTest, PixelBuffer_GLTexture) {
2776 if (GetParam() != ResourceProvider::GLTexture)
2777 return;
2778 scoped_ptr<AllocationTrackingContext3D> context_owned(
2779 new StrictMock<AllocationTrackingContext3D>);
2780 AllocationTrackingContext3D* context = context_owned.get();
2782 FakeOutputSurfaceClient output_surface_client;
2783 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
2784 context_owned.PassAs<TestWebGraphicsContext3D>()));
2785 CHECK(output_surface->BindToClient(&output_surface_client));
2787 gfx::Size size(2, 2);
2788 ResourceFormat format = RGBA_8888;
2789 ResourceProvider::ResourceId id = 0;
2790 int texture_id = 123;
2792 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
2793 output_surface.get(), shared_bitmap_manager_.get(), 0, false, 1));
2795 id = resource_provider->CreateResource(
2796 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
2797 resource_provider->AcquirePixelRasterBuffer(id);
2799 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
2800 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
2801 EXPECT_CALL(*context, asyncTexImage2DCHROMIUM(_, _, _, 2, 2, _, _, _, _))
2802 .Times(1);
2803 resource_provider->BeginSetPixels(id);
2805 EXPECT_TRUE(resource_provider->DidSetPixelsComplete(id));
2807 resource_provider->ReleasePixelRasterBuffer(id);
2809 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
2810 resource_provider->DeleteResource(id);
2812 Mock::VerifyAndClearExpectations(context);
2815 TEST_P(ResourceProviderTest, ForcingAsyncUploadToComplete) {
2816 // Only for GL textures.
2817 if (GetParam() != ResourceProvider::GLTexture)
2818 return;
2819 scoped_ptr<AllocationTrackingContext3D> context_owned(
2820 new StrictMock<AllocationTrackingContext3D>);
2821 AllocationTrackingContext3D* context = context_owned.get();
2823 FakeOutputSurfaceClient output_surface_client;
2824 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
2825 context_owned.PassAs<TestWebGraphicsContext3D>()));
2826 CHECK(output_surface->BindToClient(&output_surface_client));
2828 gfx::Size size(2, 2);
2829 ResourceFormat format = RGBA_8888;
2830 ResourceProvider::ResourceId id = 0;
2831 int texture_id = 123;
2833 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
2834 output_surface.get(), shared_bitmap_manager_.get(), 0, false, 1));
2836 id = resource_provider->CreateResource(
2837 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
2838 resource_provider->AcquirePixelRasterBuffer(id);
2840 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
2841 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
2842 EXPECT_CALL(*context, asyncTexImage2DCHROMIUM(_, _, _, 2, 2, _, _, _, _))
2843 .Times(1);
2844 resource_provider->BeginSetPixels(id);
2846 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(1);
2847 EXPECT_CALL(*context, waitAsyncTexImage2DCHROMIUM(GL_TEXTURE_2D)).Times(1);
2848 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, 0)).Times(1);
2849 resource_provider->ForceSetPixelsToComplete(id);
2851 resource_provider->ReleasePixelRasterBuffer(id);
2853 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
2854 resource_provider->DeleteResource(id);
2856 Mock::VerifyAndClearExpectations(context);
2859 TEST_P(ResourceProviderTest, PixelBufferLostContext) {
2860 scoped_ptr<AllocationTrackingContext3D> context_owned(
2861 new NiceMock<AllocationTrackingContext3D>);
2862 AllocationTrackingContext3D* context = context_owned.get();
2864 FakeOutputSurfaceClient output_surface_client;
2865 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
2866 context_owned.PassAs<TestWebGraphicsContext3D>()));
2867 CHECK(output_surface->BindToClient(&output_surface_client));
2869 gfx::Size size(2, 2);
2870 ResourceFormat format = RGBA_8888;
2871 ResourceProvider::ResourceId id = 0;
2872 int texture_id = 123;
2874 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
2875 output_surface.get(), shared_bitmap_manager_.get(), 0, false, 1));
2877 EXPECT_CALL(*context, NextTextureId()).WillRepeatedly(Return(texture_id));
2879 id = resource_provider->CreateResource(
2880 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
2881 context->loseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB,
2882 GL_INNOCENT_CONTEXT_RESET_ARB);
2884 resource_provider->AcquirePixelRasterBuffer(id);
2885 SkCanvas* raster_canvas = resource_provider->MapPixelRasterBuffer(id);
2886 EXPECT_TRUE(raster_canvas == NULL);
2887 resource_provider->UnmapPixelRasterBuffer(id);
2888 resource_provider->ReleasePixelRasterBuffer(id);
2889 Mock::VerifyAndClearExpectations(context);
2892 TEST_P(ResourceProviderTest, Image_GLTexture) {
2893 // Only for GL textures.
2894 if (GetParam() != ResourceProvider::GLTexture)
2895 return;
2896 scoped_ptr<AllocationTrackingContext3D> context_owned(
2897 new StrictMock<AllocationTrackingContext3D>);
2898 AllocationTrackingContext3D* context = context_owned.get();
2900 FakeOutputSurfaceClient output_surface_client;
2901 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
2902 context_owned.PassAs<TestWebGraphicsContext3D>()));
2903 CHECK(output_surface->BindToClient(&output_surface_client));
2905 const int kWidth = 2;
2906 const int kHeight = 2;
2907 gfx::Size size(kWidth, kHeight);
2908 ResourceFormat format = RGBA_8888;
2909 ResourceProvider::ResourceId id = 0;
2910 const unsigned kTextureId = 123u;
2911 const unsigned kImageId = 234u;
2913 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
2914 output_surface.get(), shared_bitmap_manager_.get(), 0, false, 1));
2916 id = resource_provider->CreateResource(
2917 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
2919 const int kStride = 4;
2920 void* dummy_mapped_buffer_address = NULL;
2921 EXPECT_CALL(*context, createImageCHROMIUM(kWidth, kHeight, GL_RGBA8_OES))
2922 .WillOnce(Return(kImageId))
2923 .RetiresOnSaturation();
2924 EXPECT_CALL(*context, getImageParameterivCHROMIUM(kImageId,
2925 GL_IMAGE_ROWBYTES_CHROMIUM,
2927 .WillOnce(SetArgPointee<2>(kStride))
2928 .RetiresOnSaturation();
2929 EXPECT_CALL(*context, mapImageCHROMIUM(kImageId, GL_READ_WRITE))
2930 .WillOnce(Return(dummy_mapped_buffer_address))
2931 .RetiresOnSaturation();
2932 resource_provider->MapImageRasterBuffer(id);
2934 EXPECT_CALL(*context, unmapImageCHROMIUM(kImageId))
2935 .Times(1)
2936 .RetiresOnSaturation();
2937 resource_provider->UnmapImageRasterBuffer(id);
2939 EXPECT_CALL(*context, NextTextureId())
2940 .WillOnce(Return(kTextureId))
2941 .RetiresOnSaturation();
2942 // Once in CreateTextureId and once in BindForSampling
2943 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kTextureId)).Times(2)
2944 .RetiresOnSaturation();
2945 EXPECT_CALL(*context, bindTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId))
2946 .Times(1)
2947 .RetiresOnSaturation();
2949 ResourceProvider::ScopedSamplerGL lock_gl(
2950 resource_provider.get(), id, GL_TEXTURE_2D, GL_LINEAR);
2951 EXPECT_EQ(kTextureId, lock_gl.texture_id());
2954 EXPECT_CALL(
2955 *context,
2956 getImageParameterivCHROMIUM(kImageId, GL_IMAGE_ROWBYTES_CHROMIUM, _))
2957 .WillOnce(SetArgPointee<2>(kStride))
2958 .RetiresOnSaturation();
2959 EXPECT_CALL(*context, mapImageCHROMIUM(kImageId, GL_READ_WRITE))
2960 .WillOnce(Return(dummy_mapped_buffer_address))
2961 .RetiresOnSaturation();
2962 resource_provider->MapImageRasterBuffer(id);
2964 EXPECT_CALL(*context, unmapImageCHROMIUM(kImageId))
2965 .Times(1)
2966 .RetiresOnSaturation();
2967 resource_provider->UnmapImageRasterBuffer(id);
2969 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kTextureId)).Times(1)
2970 .RetiresOnSaturation();
2971 EXPECT_CALL(*context, releaseTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId))
2972 .Times(1)
2973 .RetiresOnSaturation();
2974 EXPECT_CALL(*context, bindTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId))
2975 .Times(1)
2976 .RetiresOnSaturation();
2977 EXPECT_CALL(*context, RetireTextureId(kTextureId))
2978 .Times(1)
2979 .RetiresOnSaturation();
2981 ResourceProvider::ScopedSamplerGL lock_gl(
2982 resource_provider.get(), id, GL_TEXTURE_2D, GL_LINEAR);
2983 EXPECT_EQ(kTextureId, lock_gl.texture_id());
2986 EXPECT_CALL(*context, destroyImageCHROMIUM(kImageId))
2987 .Times(1)
2988 .RetiresOnSaturation();
2991 TEST_P(ResourceProviderTest, Image_Bitmap) {
2992 if (GetParam() != ResourceProvider::Bitmap)
2993 return;
2994 FakeOutputSurfaceClient output_surface_client;
2995 scoped_ptr<OutputSurface> output_surface(
2996 FakeOutputSurface::CreateSoftware(make_scoped_ptr(
2997 new SoftwareOutputDevice)));
2998 CHECK(output_surface->BindToClient(&output_surface_client));
3000 gfx::Size size(1, 1);
3001 ResourceFormat format = RGBA_8888;
3002 ResourceProvider::ResourceId id = 0;
3003 const uint32_t kBadBeef = 0xbadbeef;
3005 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
3006 output_surface.get(), shared_bitmap_manager_.get(), 0, false, 1));
3008 id = resource_provider->CreateResource(
3009 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
3011 SkBitmap bitmap;
3012 bitmap.allocN32Pixels(size.width(), size.height());
3013 *(bitmap.getAddr32(0, 0)) = kBadBeef;
3014 SkCanvas* canvas = resource_provider->MapImageRasterBuffer(id);
3015 ASSERT_TRUE(!!canvas);
3016 canvas->writePixels(bitmap, 0, 0);
3017 resource_provider->UnmapImageRasterBuffer(id);
3020 ResourceProvider::ScopedReadLockSoftware lock(resource_provider.get(), id);
3021 const SkBitmap* sk_bitmap = lock.sk_bitmap();
3022 EXPECT_EQ(sk_bitmap->width(), size.width());
3023 EXPECT_EQ(sk_bitmap->height(), size.height());
3024 EXPECT_EQ(*sk_bitmap->getAddr32(0, 0), kBadBeef);
3027 resource_provider->DeleteResource(id);
3030 void InitializeGLAndCheck(ContextSharedData* shared_data,
3031 ResourceProvider* resource_provider,
3032 FakeOutputSurface* output_surface) {
3033 scoped_ptr<ResourceProviderContext> context_owned =
3034 ResourceProviderContext::Create(shared_data);
3035 ResourceProviderContext* context = context_owned.get();
3037 scoped_refptr<TestContextProvider> context_provider =
3038 TestContextProvider::Create(
3039 context_owned.PassAs<TestWebGraphicsContext3D>());
3040 output_surface->InitializeAndSetContext3d(context_provider, NULL);
3041 EXPECT_TRUE(resource_provider->InitializeGL());
3043 CheckCreateResource(ResourceProvider::GLTexture, resource_provider, context);
3046 TEST(ResourceProviderTest, BasicInitializeGLSoftware) {
3047 scoped_ptr<ContextSharedData> shared_data = ContextSharedData::Create();
3048 FakeOutputSurfaceClient client;
3049 scoped_ptr<FakeOutputSurface> output_surface(
3050 FakeOutputSurface::CreateDeferredGL(
3051 scoped_ptr<SoftwareOutputDevice>(new SoftwareOutputDevice)));
3052 EXPECT_TRUE(output_surface->BindToClient(&client));
3053 scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
3054 new TestSharedBitmapManager());
3055 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
3056 output_surface.get(), shared_bitmap_manager.get(), 0, false, 1));
3058 CheckCreateResource(ResourceProvider::Bitmap, resource_provider.get(), NULL);
3060 InitializeGLAndCheck(shared_data.get(),
3061 resource_provider.get(),
3062 output_surface.get());
3064 resource_provider->InitializeSoftware();
3065 output_surface->ReleaseGL();
3066 CheckCreateResource(ResourceProvider::Bitmap, resource_provider.get(), NULL);
3068 InitializeGLAndCheck(shared_data.get(),
3069 resource_provider.get(),
3070 output_surface.get());
3073 TEST_P(ResourceProviderTest, CompressedTextureETC1Allocate) {
3074 if (GetParam() != ResourceProvider::GLTexture)
3075 return;
3077 scoped_ptr<AllocationTrackingContext3D> context_owned(
3078 new AllocationTrackingContext3D);
3079 AllocationTrackingContext3D* context = context_owned.get();
3080 context_owned->set_support_compressed_texture_etc1(true);
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(4, 4);
3088 scoped_ptr<ResourceProvider> resource_provider(
3089 ResourceProvider::Create(output_surface.get(),
3090 shared_bitmap_manager_.get(),
3092 false,
3093 1));
3094 int texture_id = 123;
3096 ResourceProvider::ResourceId id = resource_provider->CreateResource(
3097 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, ETC1);
3098 EXPECT_NE(0u, id);
3099 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3100 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
3101 resource_provider->AllocateForTesting(id);
3103 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3104 resource_provider->DeleteResource(id);
3107 TEST_P(ResourceProviderTest, CompressedTextureETC1SetPixels) {
3108 if (GetParam() != ResourceProvider::GLTexture)
3109 return;
3111 scoped_ptr<AllocationTrackingContext3D> context_owned(
3112 new AllocationTrackingContext3D);
3113 AllocationTrackingContext3D* context = context_owned.get();
3114 context_owned->set_support_compressed_texture_etc1(true);
3116 FakeOutputSurfaceClient output_surface_client;
3117 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
3118 context_owned.PassAs<TestWebGraphicsContext3D>()));
3119 CHECK(output_surface->BindToClient(&output_surface_client));
3121 gfx::Size size(4, 4);
3122 scoped_ptr<ResourceProvider> resource_provider(
3123 ResourceProvider::Create(output_surface.get(),
3124 shared_bitmap_manager_.get(),
3126 false,
3127 1));
3128 int texture_id = 123;
3129 uint8_t pixels[8];
3131 ResourceProvider::ResourceId id = resource_provider->CreateResource(
3132 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, ETC1);
3133 EXPECT_NE(0u, id);
3134 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3135 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(3);
3136 EXPECT_CALL(*context,
3137 compressedTexImage2D(
3138 _, 0, _, size.width(), size.height(), _, _, _)).Times(1);
3139 resource_provider->SetPixels(
3140 id, pixels, gfx::Rect(size), gfx::Rect(size), gfx::Vector2d(0, 0));
3142 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3143 resource_provider->DeleteResource(id);
3146 INSTANTIATE_TEST_CASE_P(
3147 ResourceProviderTests,
3148 ResourceProviderTest,
3149 ::testing::Values(ResourceProvider::GLTexture, ResourceProvider::Bitmap));
3151 class TextureIdAllocationTrackingContext : public TestWebGraphicsContext3D {
3152 public:
3153 virtual GLuint NextTextureId() OVERRIDE {
3154 base::AutoLock lock(namespace_->lock);
3155 return namespace_->next_texture_id++;
3157 virtual void RetireTextureId(GLuint) OVERRIDE {}
3158 GLuint PeekTextureId() {
3159 base::AutoLock lock(namespace_->lock);
3160 return namespace_->next_texture_id;
3164 TEST(ResourceProviderTest, TextureAllocationChunkSize) {
3165 scoped_ptr<TextureIdAllocationTrackingContext> context_owned(
3166 new TextureIdAllocationTrackingContext);
3167 TextureIdAllocationTrackingContext* context = context_owned.get();
3169 FakeOutputSurfaceClient output_surface_client;
3170 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
3171 context_owned.PassAs<TestWebGraphicsContext3D>()));
3172 CHECK(output_surface->BindToClient(&output_surface_client));
3173 scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
3174 new TestSharedBitmapManager());
3176 gfx::Size size(1, 1);
3177 ResourceFormat format = RGBA_8888;
3180 size_t kTextureAllocationChunkSize = 1;
3181 scoped_ptr<ResourceProvider> resource_provider(
3182 ResourceProvider::Create(output_surface.get(),
3183 shared_bitmap_manager.get(),
3185 false,
3186 kTextureAllocationChunkSize));
3188 ResourceProvider::ResourceId id = resource_provider->CreateResource(
3189 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
3190 resource_provider->AllocateForTesting(id);
3191 Mock::VerifyAndClearExpectations(context);
3193 DCHECK_EQ(2u, context->PeekTextureId());
3194 resource_provider->DeleteResource(id);
3198 size_t kTextureAllocationChunkSize = 8;
3199 scoped_ptr<ResourceProvider> resource_provider(
3200 ResourceProvider::Create(output_surface.get(),
3201 shared_bitmap_manager.get(),
3203 false,
3204 kTextureAllocationChunkSize));
3206 ResourceProvider::ResourceId id = resource_provider->CreateResource(
3207 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
3208 resource_provider->AllocateForTesting(id);
3209 Mock::VerifyAndClearExpectations(context);
3211 DCHECK_EQ(10u, context->PeekTextureId());
3212 resource_provider->DeleteResource(id);
3216 } // namespace
3217 } // namespace cc