Supervised user whitelists: Cleanup
[chromium-blink-merge.git] / cc / resources / resource_provider_unittest.cc
blob6cebc56613193e45b690f9587e48712c9d9351cd
1 // Copyright 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "cc/resources/resource_provider.h"
7 #include <algorithm>
8 #include <map>
9 #include <set>
11 #include "base/bind.h"
12 #include "base/containers/hash_tables.h"
13 #include "base/logging.h"
14 #include "base/memory/ref_counted.h"
15 #include "cc/base/scoped_ptr_deque.h"
16 #include "cc/output/output_surface.h"
17 #include "cc/resources/returned_resource.h"
18 #include "cc/resources/shared_bitmap_manager.h"
19 #include "cc/resources/single_release_callback.h"
20 #include "cc/test/fake_output_surface.h"
21 #include "cc/test/fake_output_surface_client.h"
22 #include "cc/test/test_gpu_memory_buffer_manager.h"
23 #include "cc/test/test_shared_bitmap_manager.h"
24 #include "cc/test/test_texture.h"
25 #include "cc/test/test_web_graphics_context_3d.h"
26 #include "cc/trees/blocking_task_runner.h"
27 #include "gpu/GLES2/gl2extchromium.h"
28 #include "testing/gmock/include/gmock/gmock.h"
29 #include "testing/gtest/include/gtest/gtest.h"
30 #include "third_party/khronos/GLES2/gl2.h"
31 #include "third_party/khronos/GLES2/gl2ext.h"
32 #include "ui/gfx/geometry/rect.h"
33 #include "ui/gfx/gpu_memory_buffer.h"
35 using testing::Mock;
36 using testing::NiceMock;
37 using testing::Return;
38 using testing::SetArgPointee;
39 using testing::StrictMock;
40 using testing::_;
42 namespace cc {
43 namespace {
45 static void EmptyReleaseCallback(uint32 sync_point,
46 bool lost_resource,
47 BlockingTaskRunner* main_thread_task_runner) {
50 static void ReleaseCallback(
51 uint32* release_sync_point,
52 bool* release_lost_resource,
53 BlockingTaskRunner** release_main_thread_task_runner,
54 uint32 sync_point,
55 bool lost_resource,
56 BlockingTaskRunner* main_thread_task_runner) {
57 *release_sync_point = sync_point;
58 *release_lost_resource = lost_resource;
59 *release_main_thread_task_runner = main_thread_task_runner;
62 static void SharedBitmapReleaseCallback(
63 scoped_ptr<SharedBitmap> bitmap,
64 uint32 sync_point,
65 bool lost_resource,
66 BlockingTaskRunner* main_thread_task_runner) {
69 static void ReleaseSharedBitmapCallback(
70 scoped_ptr<SharedBitmap> shared_bitmap,
71 bool* release_called,
72 uint32* release_sync_point,
73 bool* lost_resource_result,
74 uint32 sync_point,
75 bool lost_resource,
76 BlockingTaskRunner* main_thread_task_runner) {
77 *release_called = true;
78 *release_sync_point = sync_point;
79 *lost_resource_result = lost_resource;
82 static scoped_ptr<SharedBitmap> CreateAndFillSharedBitmap(
83 SharedBitmapManager* manager,
84 const gfx::Size& size,
85 uint32_t value) {
86 scoped_ptr<SharedBitmap> shared_bitmap = manager->AllocateSharedBitmap(size);
87 CHECK(shared_bitmap);
88 uint32_t* pixels = reinterpret_cast<uint32_t*>(shared_bitmap->pixels());
89 CHECK(pixels);
90 std::fill_n(pixels, size.GetArea(), value);
91 return shared_bitmap.Pass();
94 class TextureStateTrackingContext : public TestWebGraphicsContext3D {
95 public:
96 MOCK_METHOD2(bindTexture, void(GLenum target, GLuint texture));
97 MOCK_METHOD3(texParameteri, void(GLenum target, GLenum pname, GLint param));
98 MOCK_METHOD1(waitSyncPoint, void(GLuint sync_point));
99 MOCK_METHOD0(insertSyncPoint, GLuint(void));
100 MOCK_METHOD3(produceTextureDirectCHROMIUM,
101 void(GLuint texture, GLenum target, const GLbyte* mailbox));
102 MOCK_METHOD2(createAndConsumeTextureCHROMIUM,
103 unsigned(GLenum target, const GLbyte* mailbox));
105 // Force all textures to be consecutive numbers starting at "1",
106 // so we easily can test for them.
107 GLuint NextTextureId() override {
108 base::AutoLock lock(namespace_->lock);
109 return namespace_->next_texture_id++;
111 void RetireTextureId(GLuint) override {}
114 // Shared data between multiple ResourceProviderContext. This contains mailbox
115 // contents as well as information about sync points.
116 class ContextSharedData {
117 public:
118 static scoped_ptr<ContextSharedData> Create() {
119 return make_scoped_ptr(new ContextSharedData());
122 uint32 InsertSyncPoint() { return next_sync_point_++; }
124 void GenMailbox(GLbyte* mailbox) {
125 memset(mailbox, 0, GL_MAILBOX_SIZE_CHROMIUM);
126 memcpy(mailbox, &next_mailbox_, sizeof(next_mailbox_));
127 ++next_mailbox_;
130 void ProduceTexture(const GLbyte* mailbox_name,
131 uint32 sync_point,
132 scoped_refptr<TestTexture> texture) {
133 unsigned mailbox = 0;
134 memcpy(&mailbox, mailbox_name, sizeof(mailbox));
135 ASSERT_TRUE(mailbox && mailbox < next_mailbox_);
136 textures_[mailbox] = texture;
137 ASSERT_LT(sync_point_for_mailbox_[mailbox], sync_point);
138 sync_point_for_mailbox_[mailbox] = sync_point;
141 scoped_refptr<TestTexture> ConsumeTexture(const GLbyte* mailbox_name,
142 uint32 sync_point) {
143 unsigned mailbox = 0;
144 memcpy(&mailbox, mailbox_name, sizeof(mailbox));
145 DCHECK(mailbox && mailbox < next_mailbox_);
147 // If the latest sync point the context has waited on is before the sync
148 // point for when the mailbox was set, pretend we never saw that
149 // ProduceTexture.
150 if (sync_point_for_mailbox_[mailbox] > sync_point) {
151 NOTREACHED();
152 return scoped_refptr<TestTexture>();
154 return textures_[mailbox];
157 private:
158 ContextSharedData() : next_sync_point_(1), next_mailbox_(1) {}
160 uint32 next_sync_point_;
161 unsigned next_mailbox_;
162 typedef base::hash_map<unsigned, scoped_refptr<TestTexture>> TextureMap;
163 TextureMap textures_;
164 base::hash_map<unsigned, uint32> sync_point_for_mailbox_;
167 class ResourceProviderContext : public TestWebGraphicsContext3D {
168 public:
169 static scoped_ptr<ResourceProviderContext> Create(
170 ContextSharedData* shared_data) {
171 return make_scoped_ptr(new ResourceProviderContext(shared_data));
174 GLuint insertSyncPoint() override {
175 uint32 sync_point = shared_data_->InsertSyncPoint();
176 // Commit the produceTextureCHROMIUM calls at this point, so that
177 // they're associated with the sync point.
178 for (PendingProduceTextureList::iterator it =
179 pending_produce_textures_.begin();
180 it != pending_produce_textures_.end();
181 ++it) {
182 shared_data_->ProduceTexture(
183 (*it)->mailbox, sync_point, (*it)->texture);
185 pending_produce_textures_.clear();
186 return sync_point;
189 void waitSyncPoint(GLuint sync_point) override {
190 last_waited_sync_point_ = std::max(sync_point, last_waited_sync_point_);
193 unsigned last_waited_sync_point() const { return last_waited_sync_point_; }
195 void texStorage2DEXT(GLenum target,
196 GLint levels,
197 GLuint internalformat,
198 GLint width,
199 GLint height) override {
200 CheckTextureIsBound(target);
201 ASSERT_EQ(static_cast<unsigned>(GL_TEXTURE_2D), target);
202 ASSERT_EQ(1, levels);
203 GLenum format = GL_RGBA;
204 switch (internalformat) {
205 case GL_RGBA8_OES:
206 break;
207 case GL_BGRA8_EXT:
208 format = GL_BGRA_EXT;
209 break;
210 default:
211 NOTREACHED();
213 AllocateTexture(gfx::Size(width, height), format);
216 void texImage2D(GLenum target,
217 GLint level,
218 GLenum internalformat,
219 GLsizei width,
220 GLsizei height,
221 GLint border,
222 GLenum format,
223 GLenum type,
224 const void* pixels) override {
225 CheckTextureIsBound(target);
226 ASSERT_EQ(static_cast<unsigned>(GL_TEXTURE_2D), target);
227 ASSERT_FALSE(level);
228 ASSERT_EQ(internalformat, format);
229 ASSERT_FALSE(border);
230 ASSERT_EQ(static_cast<unsigned>(GL_UNSIGNED_BYTE), type);
231 AllocateTexture(gfx::Size(width, height), format);
232 if (pixels)
233 SetPixels(0, 0, width, height, pixels);
236 void texSubImage2D(GLenum target,
237 GLint level,
238 GLint xoffset,
239 GLint yoffset,
240 GLsizei width,
241 GLsizei height,
242 GLenum format,
243 GLenum type,
244 const void* pixels) override {
245 CheckTextureIsBound(target);
246 ASSERT_EQ(static_cast<unsigned>(GL_TEXTURE_2D), target);
247 ASSERT_FALSE(level);
248 ASSERT_EQ(static_cast<unsigned>(GL_UNSIGNED_BYTE), type);
250 base::AutoLock lock_for_texture_access(namespace_->lock);
251 ASSERT_EQ(GLDataFormat(BoundTexture(target)->format), format);
253 ASSERT_TRUE(pixels);
254 SetPixels(xoffset, yoffset, width, height, pixels);
257 void genMailboxCHROMIUM(GLbyte* mailbox) override {
258 return shared_data_->GenMailbox(mailbox);
261 void produceTextureDirectCHROMIUM(GLuint texture,
262 GLenum target,
263 const GLbyte* mailbox) override {
264 // Delay moving the texture into the mailbox until the next
265 // InsertSyncPoint, so that it is not visible to other contexts that
266 // haven't waited on that sync point.
267 scoped_ptr<PendingProduceTexture> pending(new PendingProduceTexture);
268 memcpy(pending->mailbox, mailbox, sizeof(pending->mailbox));
269 base::AutoLock lock_for_texture_access(namespace_->lock);
270 pending->texture = UnboundTexture(texture);
271 pending_produce_textures_.push_back(pending.Pass());
274 GLuint createAndConsumeTextureCHROMIUM(GLenum target,
275 const GLbyte* mailbox) override {
276 GLuint texture_id = createTexture();
277 base::AutoLock lock_for_texture_access(namespace_->lock);
278 scoped_refptr<TestTexture> texture =
279 shared_data_->ConsumeTexture(mailbox, last_waited_sync_point_);
280 namespace_->textures.Replace(texture_id, texture);
281 return texture_id;
284 void GetPixels(const gfx::Size& size,
285 ResourceFormat format,
286 uint8_t* pixels) {
287 CheckTextureIsBound(GL_TEXTURE_2D);
288 base::AutoLock lock_for_texture_access(namespace_->lock);
289 scoped_refptr<TestTexture> texture = BoundTexture(GL_TEXTURE_2D);
290 ASSERT_EQ(texture->size, size);
291 ASSERT_EQ(texture->format, format);
292 memcpy(pixels, texture->data.get(), TextureSizeBytes(size, format));
295 protected:
296 explicit ResourceProviderContext(ContextSharedData* shared_data)
297 : shared_data_(shared_data),
298 last_waited_sync_point_(0) {}
300 private:
301 void AllocateTexture(const gfx::Size& size, GLenum format) {
302 CheckTextureIsBound(GL_TEXTURE_2D);
303 ResourceFormat texture_format = RGBA_8888;
304 switch (format) {
305 case GL_RGBA:
306 texture_format = RGBA_8888;
307 break;
308 case GL_BGRA_EXT:
309 texture_format = BGRA_8888;
310 break;
312 base::AutoLock lock_for_texture_access(namespace_->lock);
313 BoundTexture(GL_TEXTURE_2D)->Reallocate(size, texture_format);
316 void SetPixels(int xoffset,
317 int yoffset,
318 int width,
319 int height,
320 const void* pixels) {
321 CheckTextureIsBound(GL_TEXTURE_2D);
322 base::AutoLock lock_for_texture_access(namespace_->lock);
323 scoped_refptr<TestTexture> texture = BoundTexture(GL_TEXTURE_2D);
324 ASSERT_TRUE(texture->data.get());
325 ASSERT_TRUE(xoffset >= 0 && xoffset + width <= texture->size.width());
326 ASSERT_TRUE(yoffset >= 0 && yoffset + height <= texture->size.height());
327 ASSERT_TRUE(pixels);
328 size_t in_pitch = TextureSizeBytes(gfx::Size(width, 1), texture->format);
329 size_t out_pitch =
330 TextureSizeBytes(gfx::Size(texture->size.width(), 1), texture->format);
331 uint8_t* dest = texture->data.get() + yoffset * out_pitch +
332 TextureSizeBytes(gfx::Size(xoffset, 1), texture->format);
333 const uint8_t* src = static_cast<const uint8_t*>(pixels);
334 for (int i = 0; i < height; ++i) {
335 memcpy(dest, src, in_pitch);
336 dest += out_pitch;
337 src += in_pitch;
341 struct PendingProduceTexture {
342 GLbyte mailbox[GL_MAILBOX_SIZE_CHROMIUM];
343 scoped_refptr<TestTexture> texture;
345 typedef ScopedPtrDeque<PendingProduceTexture> PendingProduceTextureList;
346 ContextSharedData* shared_data_;
347 GLuint last_waited_sync_point_;
348 PendingProduceTextureList pending_produce_textures_;
351 void GetResourcePixels(ResourceProvider* resource_provider,
352 ResourceProviderContext* context,
353 ResourceProvider::ResourceId id,
354 const gfx::Size& size,
355 ResourceFormat format,
356 uint8_t* pixels) {
357 resource_provider->WaitSyncPointIfNeeded(id);
358 switch (resource_provider->default_resource_type()) {
359 case ResourceProvider::RESOURCE_TYPE_GL_TEXTURE: {
360 ResourceProvider::ScopedReadLockGL lock_gl(resource_provider, id);
361 ASSERT_NE(0U, lock_gl.texture_id());
362 context->bindTexture(GL_TEXTURE_2D, lock_gl.texture_id());
363 context->GetPixels(size, format, pixels);
364 break;
366 case ResourceProvider::RESOURCE_TYPE_BITMAP: {
367 ResourceProvider::ScopedReadLockSoftware lock_software(resource_provider,
368 id);
369 memcpy(pixels,
370 lock_software.sk_bitmap()->getPixels(),
371 lock_software.sk_bitmap()->getSize());
372 break;
377 class ResourceProviderTest
378 : public testing::TestWithParam<ResourceProvider::ResourceType> {
379 public:
380 explicit ResourceProviderTest(bool child_needs_sync_point)
381 : shared_data_(ContextSharedData::Create()),
382 context3d_(NULL),
383 child_context_(NULL),
384 main_thread_task_runner_(BlockingTaskRunner::Create(NULL)) {
385 switch (GetParam()) {
386 case ResourceProvider::RESOURCE_TYPE_GL_TEXTURE: {
387 scoped_ptr<ResourceProviderContext> context3d(
388 ResourceProviderContext::Create(shared_data_.get()));
389 context3d_ = context3d.get();
391 scoped_refptr<TestContextProvider> context_provider =
392 TestContextProvider::Create(context3d.Pass());
394 output_surface_ = FakeOutputSurface::Create3d(context_provider);
396 scoped_ptr<ResourceProviderContext> child_context_owned =
397 ResourceProviderContext::Create(shared_data_.get());
398 child_context_ = child_context_owned.get();
399 if (child_needs_sync_point) {
400 child_output_surface_ =
401 FakeOutputSurface::Create3d(child_context_owned.Pass());
402 } else {
403 child_output_surface_ = FakeOutputSurface::CreateNoRequireSyncPoint(
404 child_context_owned.Pass());
406 break;
408 case ResourceProvider::RESOURCE_TYPE_BITMAP:
409 output_surface_ = FakeOutputSurface::CreateSoftware(
410 make_scoped_ptr(new SoftwareOutputDevice));
411 child_output_surface_ = FakeOutputSurface::CreateSoftware(
412 make_scoped_ptr(new SoftwareOutputDevice));
413 break;
415 CHECK(output_surface_->BindToClient(&output_surface_client_));
416 CHECK(child_output_surface_->BindToClient(&child_output_surface_client_));
418 shared_bitmap_manager_.reset(new TestSharedBitmapManager);
419 gpu_memory_buffer_manager_.reset(new TestGpuMemoryBufferManager);
421 resource_provider_ =
422 ResourceProvider::Create(output_surface_.get(),
423 shared_bitmap_manager_.get(),
424 gpu_memory_buffer_manager_.get(),
425 main_thread_task_runner_.get(),
427 false,
429 child_resource_provider_ =
430 ResourceProvider::Create(child_output_surface_.get(),
431 shared_bitmap_manager_.get(),
432 gpu_memory_buffer_manager_.get(),
433 main_thread_task_runner_.get(),
435 false,
439 ResourceProviderTest() : ResourceProviderTest(true) {}
441 static void CollectResources(ReturnedResourceArray* array,
442 const ReturnedResourceArray& returned,
443 BlockingTaskRunner* main_thread_task_runner) {
444 array->insert(array->end(), returned.begin(), returned.end());
447 static ReturnCallback GetReturnCallback(ReturnedResourceArray* array) {
448 return base::Bind(&ResourceProviderTest::CollectResources, array);
451 static void SetResourceFilter(ResourceProvider* resource_provider,
452 ResourceProvider::ResourceId id,
453 GLenum filter) {
454 ResourceProvider::ScopedSamplerGL sampler(
455 resource_provider, id, GL_TEXTURE_2D, filter);
458 ResourceProviderContext* context() { return context3d_; }
460 ResourceProvider::ResourceId CreateChildMailbox(uint32* release_sync_point,
461 bool* lost_resource,
462 bool* release_called,
463 uint32* sync_point) {
464 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) {
465 unsigned texture = child_context_->createTexture();
466 gpu::Mailbox gpu_mailbox;
467 child_context_->genMailboxCHROMIUM(gpu_mailbox.name);
468 child_context_->produceTextureDirectCHROMIUM(texture, GL_TEXTURE_2D,
469 gpu_mailbox.name);
470 *sync_point = child_context_->insertSyncPoint();
471 EXPECT_LT(0u, *sync_point);
473 scoped_ptr<SharedBitmap> shared_bitmap;
474 scoped_ptr<SingleReleaseCallbackImpl> callback =
475 SingleReleaseCallbackImpl::Create(base::Bind(
476 ReleaseSharedBitmapCallback, base::Passed(&shared_bitmap),
477 release_called, release_sync_point, lost_resource));
478 return child_resource_provider_->CreateResourceFromTextureMailbox(
479 TextureMailbox(gpu_mailbox, GL_TEXTURE_2D, *sync_point),
480 callback.Pass());
481 } else {
482 gfx::Size size(64, 64);
483 scoped_ptr<SharedBitmap> shared_bitmap(
484 CreateAndFillSharedBitmap(shared_bitmap_manager_.get(), size, 0));
486 SharedBitmap* shared_bitmap_ptr = shared_bitmap.get();
487 scoped_ptr<SingleReleaseCallbackImpl> callback =
488 SingleReleaseCallbackImpl::Create(base::Bind(
489 ReleaseSharedBitmapCallback, base::Passed(&shared_bitmap),
490 release_called, release_sync_point, lost_resource));
491 return child_resource_provider_->CreateResourceFromTextureMailbox(
492 TextureMailbox(shared_bitmap_ptr, size), callback.Pass());
496 protected:
497 scoped_ptr<ContextSharedData> shared_data_;
498 ResourceProviderContext* context3d_;
499 ResourceProviderContext* child_context_;
500 FakeOutputSurfaceClient output_surface_client_;
501 FakeOutputSurfaceClient child_output_surface_client_;
502 scoped_ptr<OutputSurface> output_surface_;
503 scoped_ptr<OutputSurface> child_output_surface_;
504 scoped_ptr<BlockingTaskRunner> main_thread_task_runner_;
505 scoped_ptr<ResourceProvider> resource_provider_;
506 scoped_ptr<ResourceProvider> child_resource_provider_;
507 scoped_ptr<TestSharedBitmapManager> shared_bitmap_manager_;
508 scoped_ptr<TestGpuMemoryBufferManager> gpu_memory_buffer_manager_;
511 void CheckCreateResource(ResourceProvider::ResourceType expected_default_type,
512 ResourceProvider* resource_provider,
513 ResourceProviderContext* context) {
514 DCHECK_EQ(expected_default_type, resource_provider->default_resource_type());
516 gfx::Size size(1, 1);
517 ResourceFormat format = RGBA_8888;
518 size_t pixel_size = TextureSizeBytes(size, format);
519 ASSERT_EQ(4U, pixel_size);
521 ResourceProvider::ResourceId id = resource_provider->CreateResource(
522 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
523 EXPECT_EQ(1, static_cast<int>(resource_provider->num_resources()));
524 if (expected_default_type == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
525 EXPECT_EQ(0u, context->NumTextures());
527 uint8_t data[4] = { 1, 2, 3, 4 };
528 resource_provider->CopyToResource(id, data, size);
529 if (expected_default_type == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
530 EXPECT_EQ(1u, context->NumTextures());
532 uint8_t result[4] = { 0 };
533 GetResourcePixels(resource_provider, context, id, size, format, result);
534 EXPECT_EQ(0, memcmp(data, result, pixel_size));
536 resource_provider->DeleteResource(id);
537 EXPECT_EQ(0, static_cast<int>(resource_provider->num_resources()));
538 if (expected_default_type == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
539 EXPECT_EQ(0u, context->NumTextures());
542 TEST_P(ResourceProviderTest, Basic) {
543 CheckCreateResource(GetParam(), resource_provider_.get(), context());
546 TEST_P(ResourceProviderTest, Upload) {
547 gfx::Size size(2, 2);
548 ResourceFormat format = RGBA_8888;
549 size_t pixel_size = TextureSizeBytes(size, format);
550 ASSERT_EQ(16U, pixel_size);
552 ResourceProvider::ResourceId id = resource_provider_->CreateResource(
553 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
555 uint8_t image[16] = { 0 };
556 gfx::Rect image_rect(size);
557 resource_provider_->SetPixels(
558 id, image, image_rect, image_rect, gfx::Vector2d());
560 for (uint8_t i = 0; i < pixel_size; ++i)
561 image[i] = i;
563 uint8_t result[16] = { 0 };
565 gfx::Rect source_rect(0, 0, 1, 1);
566 gfx::Vector2d dest_offset(0, 0);
567 resource_provider_->SetPixels(
568 id, image, image_rect, source_rect, dest_offset);
570 uint8_t expected[16] = { 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
571 GetResourcePixels(
572 resource_provider_.get(), context(), id, size, format, result);
573 EXPECT_EQ(0, memcmp(expected, result, pixel_size));
576 gfx::Rect source_rect(0, 0, 1, 1);
577 gfx::Vector2d dest_offset(1, 1);
578 resource_provider_->SetPixels(
579 id, image, image_rect, source_rect, dest_offset);
581 uint8_t expected[16] = { 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3 };
582 GetResourcePixels(
583 resource_provider_.get(), context(), id, size, format, result);
584 EXPECT_EQ(0, memcmp(expected, result, pixel_size));
587 gfx::Rect source_rect(1, 0, 1, 1);
588 gfx::Vector2d dest_offset(0, 1);
589 resource_provider_->SetPixels(
590 id, image, image_rect, source_rect, dest_offset);
592 uint8_t expected[16] = { 0, 1, 2, 3, 0, 0, 0, 0, 4, 5, 6, 7, 0, 1, 2, 3 };
593 GetResourcePixels(
594 resource_provider_.get(), context(), id, size, format, result);
595 EXPECT_EQ(0, memcmp(expected, result, pixel_size));
598 gfx::Rect offset_image_rect(gfx::Point(100, 100), size);
599 gfx::Rect source_rect(100, 100, 1, 1);
600 gfx::Vector2d dest_offset(1, 0);
601 resource_provider_->SetPixels(
602 id, image, offset_image_rect, source_rect, dest_offset);
604 uint8_t expected[16] = { 0, 1, 2, 3, 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3 };
605 GetResourcePixels(
606 resource_provider_.get(), context(), id, size, format, result);
607 EXPECT_EQ(0, memcmp(expected, result, pixel_size));
610 resource_provider_->DeleteResource(id);
613 TEST_P(ResourceProviderTest, SimpleUpload) {
614 gfx::Size size(2, 2);
615 ResourceFormat format = RGBA_8888;
616 size_t pixel_size = TextureSizeBytes(size, format);
617 ASSERT_EQ(16U, pixel_size);
619 ResourceProvider::ResourceId id = resource_provider_->CreateResource(
620 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
622 uint8_t image[16] = {0};
623 resource_provider_->CopyToResource(id, image, size);
625 uint8_t result[16] = {0};
626 uint8_t expected[16] = {0};
627 GetResourcePixels(resource_provider_.get(), context(), id, size, format,
628 result);
629 EXPECT_EQ(0, memcmp(expected, result, pixel_size));
632 for (uint8_t i = 0; i < pixel_size; ++i)
633 image[i] = i;
634 resource_provider_->CopyToResource(id, image, size);
636 uint8_t result[16] = {0};
637 uint8_t expected[16] = {
638 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
639 GetResourcePixels(resource_provider_.get(), context(), id, size, format,
640 result);
641 EXPECT_EQ(0, memcmp(expected, result, pixel_size));
645 TEST_P(ResourceProviderTest, TransferGLResources) {
646 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
647 return;
648 gfx::Size size(1, 1);
649 ResourceFormat format = RGBA_8888;
650 size_t pixel_size = TextureSizeBytes(size, format);
651 ASSERT_EQ(4U, pixel_size);
653 ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource(
654 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
655 uint8_t data1[4] = { 1, 2, 3, 4 };
656 child_resource_provider_->CopyToResource(id1, data1, size);
658 ResourceProvider::ResourceId id2 = child_resource_provider_->CreateResource(
659 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
660 uint8_t data2[4] = { 5, 5, 5, 5 };
661 child_resource_provider_->CopyToResource(id2, data2, size);
663 ResourceProvider::ResourceId id3 = child_resource_provider_->CreateResource(
664 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
666 ResourceProvider::ScopedWriteLockGpuMemoryBuffer lock(
667 child_resource_provider_.get(), id3);
668 EXPECT_TRUE(!!lock.GetGpuMemoryBuffer());
671 GLuint external_texture_id = child_context_->createExternalTexture();
673 gpu::Mailbox external_mailbox;
674 child_context_->genMailboxCHROMIUM(external_mailbox.name);
675 child_context_->produceTextureDirectCHROMIUM(
676 external_texture_id, GL_TEXTURE_EXTERNAL_OES, external_mailbox.name);
677 const GLuint external_sync_point = child_context_->insertSyncPoint();
678 ResourceProvider::ResourceId id4 =
679 child_resource_provider_->CreateResourceFromTextureMailbox(
680 TextureMailbox(
681 external_mailbox, GL_TEXTURE_EXTERNAL_OES, external_sync_point),
682 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback)));
684 ReturnedResourceArray returned_to_child;
685 int child_id =
686 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
688 // Transfer some resources to the parent.
689 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
690 resource_ids_to_transfer.push_back(id1);
691 resource_ids_to_transfer.push_back(id2);
692 resource_ids_to_transfer.push_back(id3);
693 resource_ids_to_transfer.push_back(id4);
694 TransferableResourceArray list;
695 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
696 &list);
697 ASSERT_EQ(4u, list.size());
698 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
699 EXPECT_NE(0u, list[1].mailbox_holder.sync_point);
700 EXPECT_EQ(list[0].mailbox_holder.sync_point,
701 list[1].mailbox_holder.sync_point);
702 EXPECT_NE(0u, list[2].mailbox_holder.sync_point);
703 EXPECT_EQ(list[0].mailbox_holder.sync_point,
704 list[2].mailbox_holder.sync_point);
705 EXPECT_EQ(external_sync_point, list[3].mailbox_holder.sync_point);
706 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
707 list[0].mailbox_holder.texture_target);
708 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
709 list[1].mailbox_holder.texture_target);
710 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
711 list[2].mailbox_holder.texture_target);
712 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_EXTERNAL_OES),
713 list[3].mailbox_holder.texture_target);
714 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
715 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
716 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
717 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id4));
718 resource_provider_->ReceiveFromChild(child_id, list);
719 EXPECT_NE(list[0].mailbox_holder.sync_point,
720 context3d_->last_waited_sync_point());
722 resource_provider_->WaitSyncPointIfNeeded(list[0].id);
723 ResourceProvider::ScopedReadLockGL lock(resource_provider_.get(),
724 list[0].id);
726 EXPECT_EQ(list[0].mailbox_holder.sync_point,
727 context3d_->last_waited_sync_point());
728 ResourceProvider::ResourceIdSet resource_ids_to_receive;
729 resource_ids_to_receive.insert(id1);
730 resource_ids_to_receive.insert(id2);
731 resource_ids_to_receive.insert(id3);
732 resource_ids_to_receive.insert(id4);
733 resource_provider_->DeclareUsedResourcesFromChild(child_id,
734 resource_ids_to_receive);
737 EXPECT_EQ(4u, resource_provider_->num_resources());
738 ResourceProvider::ResourceIdMap resource_map =
739 resource_provider_->GetChildToParentMap(child_id);
740 ResourceProvider::ResourceId mapped_id1 = resource_map[id1];
741 ResourceProvider::ResourceId mapped_id2 = resource_map[id2];
742 ResourceProvider::ResourceId mapped_id3 = resource_map[id3];
743 ResourceProvider::ResourceId mapped_id4 = resource_map[id4];
744 EXPECT_NE(0u, mapped_id1);
745 EXPECT_NE(0u, mapped_id2);
746 EXPECT_NE(0u, mapped_id3);
747 EXPECT_NE(0u, mapped_id4);
748 EXPECT_FALSE(resource_provider_->InUseByConsumer(id1));
749 EXPECT_FALSE(resource_provider_->InUseByConsumer(id2));
750 EXPECT_FALSE(resource_provider_->InUseByConsumer(id3));
751 EXPECT_FALSE(resource_provider_->InUseByConsumer(id4));
753 uint8_t result[4] = { 0 };
754 GetResourcePixels(
755 resource_provider_.get(), context(), mapped_id1, size, format, result);
756 EXPECT_EQ(0, memcmp(data1, result, pixel_size));
758 GetResourcePixels(
759 resource_provider_.get(), context(), mapped_id2, size, format, result);
760 EXPECT_EQ(0, memcmp(data2, result, pixel_size));
763 // Check that transfering again the same resource from the child to the
764 // parent works.
765 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
766 resource_ids_to_transfer.push_back(id1);
767 resource_ids_to_transfer.push_back(id2);
768 resource_ids_to_transfer.push_back(id3);
769 TransferableResourceArray list;
770 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
771 &list);
772 EXPECT_EQ(3u, list.size());
773 EXPECT_EQ(id1, list[0].id);
774 EXPECT_EQ(id2, list[1].id);
775 EXPECT_EQ(id3, list[2].id);
776 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
777 list[0].mailbox_holder.texture_target);
778 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
779 list[1].mailbox_holder.texture_target);
780 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
781 list[2].mailbox_holder.texture_target);
782 ReturnedResourceArray returned;
783 TransferableResource::ReturnResources(list, &returned);
784 child_resource_provider_->ReceiveReturnsFromParent(returned);
785 // ids were exported twice, we returned them only once, they should still
786 // be in-use.
787 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
788 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
789 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
792 EXPECT_EQ(0u, returned_to_child.size());
794 // Transfer resources back from the parent to the child. Set no resources as
795 // being in use.
796 ResourceProvider::ResourceIdSet no_resources;
797 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
799 ASSERT_EQ(4u, returned_to_child.size());
800 EXPECT_NE(0u, returned_to_child[0].sync_point);
801 EXPECT_NE(0u, returned_to_child[1].sync_point);
802 EXPECT_NE(0u, returned_to_child[2].sync_point);
803 EXPECT_NE(0u, returned_to_child[3].sync_point);
804 EXPECT_FALSE(returned_to_child[0].lost);
805 EXPECT_FALSE(returned_to_child[1].lost);
806 EXPECT_FALSE(returned_to_child[2].lost);
807 EXPECT_FALSE(returned_to_child[3].lost);
808 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
809 returned_to_child.clear();
811 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id1));
812 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id2));
813 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id3));
814 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id4));
817 child_resource_provider_->WaitSyncPointIfNeeded(id1);
818 ResourceProvider::ScopedReadLockGL lock(child_resource_provider_.get(),
819 id1);
820 ASSERT_NE(0U, lock.texture_id());
821 child_context_->bindTexture(GL_TEXTURE_2D, lock.texture_id());
822 child_context_->GetPixels(size, format, result);
823 EXPECT_EQ(0, memcmp(data1, result, pixel_size));
826 child_resource_provider_->WaitSyncPointIfNeeded(id2);
827 ResourceProvider::ScopedReadLockGL lock(child_resource_provider_.get(),
828 id2);
829 ASSERT_NE(0U, lock.texture_id());
830 child_context_->bindTexture(GL_TEXTURE_2D, lock.texture_id());
831 child_context_->GetPixels(size, format, result);
832 EXPECT_EQ(0, memcmp(data2, result, pixel_size));
835 child_resource_provider_->WaitSyncPointIfNeeded(id3);
836 ResourceProvider::ScopedReadLockGL lock(child_resource_provider_.get(),
837 id3);
838 ASSERT_NE(0U, lock.texture_id());
839 child_context_->bindTexture(GL_TEXTURE_2D, lock.texture_id());
842 // Transfer resources to the parent again.
843 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
844 resource_ids_to_transfer.push_back(id1);
845 resource_ids_to_transfer.push_back(id2);
846 resource_ids_to_transfer.push_back(id3);
847 resource_ids_to_transfer.push_back(id4);
848 TransferableResourceArray list;
849 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
850 &list);
851 ASSERT_EQ(4u, list.size());
852 EXPECT_EQ(id1, list[0].id);
853 EXPECT_EQ(id2, list[1].id);
854 EXPECT_EQ(id3, list[2].id);
855 EXPECT_EQ(id4, list[3].id);
856 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
857 EXPECT_NE(0u, list[1].mailbox_holder.sync_point);
858 EXPECT_NE(0u, list[2].mailbox_holder.sync_point);
859 EXPECT_NE(0u, list[3].mailbox_holder.sync_point);
860 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
861 list[0].mailbox_holder.texture_target);
862 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
863 list[1].mailbox_holder.texture_target);
864 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
865 list[2].mailbox_holder.texture_target);
866 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_EXTERNAL_OES),
867 list[3].mailbox_holder.texture_target);
868 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
869 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
870 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
871 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id4));
872 resource_provider_->ReceiveFromChild(child_id, list);
873 ResourceProvider::ResourceIdSet resource_ids_to_receive;
874 resource_ids_to_receive.insert(id1);
875 resource_ids_to_receive.insert(id2);
876 resource_ids_to_receive.insert(id3);
877 resource_ids_to_receive.insert(id4);
878 resource_provider_->DeclareUsedResourcesFromChild(child_id,
879 resource_ids_to_receive);
882 EXPECT_EQ(0u, returned_to_child.size());
884 EXPECT_EQ(4u, resource_provider_->num_resources());
885 resource_provider_->DestroyChild(child_id);
886 EXPECT_EQ(0u, resource_provider_->num_resources());
888 ASSERT_EQ(4u, returned_to_child.size());
889 EXPECT_NE(0u, returned_to_child[0].sync_point);
890 EXPECT_NE(0u, returned_to_child[1].sync_point);
891 EXPECT_NE(0u, returned_to_child[2].sync_point);
892 EXPECT_NE(0u, returned_to_child[3].sync_point);
893 EXPECT_FALSE(returned_to_child[0].lost);
894 EXPECT_FALSE(returned_to_child[1].lost);
895 EXPECT_FALSE(returned_to_child[2].lost);
896 EXPECT_FALSE(returned_to_child[3].lost);
899 class ResourceProviderTestNoSyncPoint : public ResourceProviderTest {
900 public:
901 ResourceProviderTestNoSyncPoint() : ResourceProviderTest(false) {
902 EXPECT_EQ(ResourceProvider::RESOURCE_TYPE_GL_TEXTURE, GetParam());
906 TEST_P(ResourceProviderTestNoSyncPoint, TransferGLResources) {
907 gfx::Size size(1, 1);
908 ResourceFormat format = RGBA_8888;
909 size_t pixel_size = TextureSizeBytes(size, format);
910 ASSERT_EQ(4U, pixel_size);
912 ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource(
913 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
914 uint8_t data1[4] = {1, 2, 3, 4};
915 child_resource_provider_->CopyToResource(id1, data1, size);
917 ResourceProvider::ResourceId id2 = child_resource_provider_->CreateResource(
918 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
920 // Ensure locking the memory buffer doesn't create an unnecessary sync
921 // point.
922 ResourceProvider::ScopedWriteLockGpuMemoryBuffer lock(
923 child_resource_provider_.get(), id2);
924 EXPECT_TRUE(!!lock.GetGpuMemoryBuffer());
927 GLuint external_texture_id = child_context_->createExternalTexture();
929 // A sync point is specified directly and should be used.
930 gpu::Mailbox external_mailbox;
931 child_context_->genMailboxCHROMIUM(external_mailbox.name);
932 child_context_->produceTextureDirectCHROMIUM(
933 external_texture_id, GL_TEXTURE_EXTERNAL_OES, external_mailbox.name);
934 const GLuint external_sync_point = child_context_->insertSyncPoint();
935 ResourceProvider::ResourceId id3 =
936 child_resource_provider_->CreateResourceFromTextureMailbox(
937 TextureMailbox(external_mailbox, GL_TEXTURE_EXTERNAL_OES,
938 external_sync_point),
939 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback)));
941 ReturnedResourceArray returned_to_child;
942 int child_id =
943 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
944 resource_provider_->SetChildNeedsSyncPoints(child_id, false);
946 // Transfer some resources to the parent.
947 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
948 resource_ids_to_transfer.push_back(id1);
949 resource_ids_to_transfer.push_back(id2);
950 resource_ids_to_transfer.push_back(id3);
951 TransferableResourceArray list;
952 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
953 &list);
954 ASSERT_EQ(3u, list.size());
955 // Standard resources shouldn't require creating and sending a sync point.
956 EXPECT_EQ(0u, list[0].mailbox_holder.sync_point);
957 EXPECT_EQ(0u, list[1].mailbox_holder.sync_point);
958 // A given sync point should be passed through.
959 EXPECT_EQ(external_sync_point, list[2].mailbox_holder.sync_point);
960 resource_provider_->ReceiveFromChild(child_id, list);
962 ResourceProvider::ResourceIdSet resource_ids_to_receive;
963 resource_ids_to_receive.insert(id1);
964 resource_ids_to_receive.insert(id2);
965 resource_ids_to_receive.insert(id3);
966 resource_provider_->DeclareUsedResourcesFromChild(child_id,
967 resource_ids_to_receive);
971 EXPECT_EQ(0u, returned_to_child.size());
973 // Transfer resources back from the parent to the child. Set no resources as
974 // being in use.
975 ResourceProvider::ResourceIdSet no_resources;
976 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
978 ASSERT_EQ(3u, returned_to_child.size());
979 std::map<ResourceProvider::ResourceId, unsigned int> returned_sync_points;
980 for (const auto& returned : returned_to_child)
981 returned_sync_points[returned.id] = returned.sync_point;
983 EXPECT_TRUE(returned_sync_points.find(id1) != returned_sync_points.end());
984 // No new sync point should be created transferring back.
985 EXPECT_TRUE(returned_sync_points.find(id1) != returned_sync_points.end());
986 EXPECT_EQ(0u, returned_sync_points[id1]);
987 EXPECT_TRUE(returned_sync_points.find(id2) != returned_sync_points.end());
988 EXPECT_EQ(0u, returned_sync_points[id2]);
989 // Original sync point given should be returned.
990 EXPECT_TRUE(returned_sync_points.find(id3) != returned_sync_points.end());
991 EXPECT_EQ(external_sync_point, returned_sync_points[id3]);
992 EXPECT_FALSE(returned_to_child[0].lost);
993 EXPECT_FALSE(returned_to_child[1].lost);
994 EXPECT_FALSE(returned_to_child[2].lost);
995 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
996 returned_to_child.clear();
999 resource_provider_->DestroyChild(child_id);
1002 INSTANTIATE_TEST_CASE_P(
1003 ResourceProviderTests,
1004 ResourceProviderTestNoSyncPoint,
1005 ::testing::Values(ResourceProvider::RESOURCE_TYPE_GL_TEXTURE));
1007 TEST_P(ResourceProviderTest, ReadLockCountStopsReturnToChildOrDelete) {
1008 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
1009 return;
1010 gfx::Size size(1, 1);
1011 ResourceFormat format = RGBA_8888;
1013 ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource(
1014 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
1015 uint8_t data1[4] = {1, 2, 3, 4};
1016 child_resource_provider_->CopyToResource(id1, data1, size);
1018 ReturnedResourceArray returned_to_child;
1019 int child_id =
1020 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1022 // Transfer some resources to the parent.
1023 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1024 resource_ids_to_transfer.push_back(id1);
1025 TransferableResourceArray list;
1026 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1027 &list);
1028 ASSERT_EQ(1u, list.size());
1029 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1031 resource_provider_->ReceiveFromChild(child_id, list);
1033 resource_provider_->WaitSyncPointIfNeeded(list[0].id);
1034 ResourceProvider::ScopedReadLockGL lock(resource_provider_.get(),
1035 list[0].id);
1037 resource_provider_->DeclareUsedResourcesFromChild(
1038 child_id, ResourceProvider::ResourceIdSet());
1039 EXPECT_EQ(0u, returned_to_child.size());
1042 EXPECT_EQ(1u, returned_to_child.size());
1043 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
1046 child_resource_provider_->WaitSyncPointIfNeeded(id1);
1047 ResourceProvider::ScopedReadLockGL lock(child_resource_provider_.get(),
1048 id1);
1049 child_resource_provider_->DeleteResource(id1);
1050 EXPECT_EQ(1u, child_resource_provider_->num_resources());
1051 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1054 EXPECT_EQ(0u, child_resource_provider_->num_resources());
1055 resource_provider_->DestroyChild(child_id);
1058 TEST_P(ResourceProviderTest, AllowOverlayTransfersToParent) {
1059 // Overlays only supported on the GL path.
1060 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
1061 return;
1063 uint32 sync_point = 0;
1064 TextureMailbox mailbox(gpu::Mailbox::Generate(), GL_TEXTURE_2D, sync_point);
1065 mailbox.set_allow_overlay(true);
1066 scoped_ptr<SingleReleaseCallbackImpl> release_callback =
1067 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback));
1068 ResourceProvider::ResourceId id1 =
1069 child_resource_provider_->CreateResourceFromTextureMailbox(
1070 mailbox, release_callback.Pass());
1072 TextureMailbox mailbox2(gpu::Mailbox::Generate(), GL_TEXTURE_2D, sync_point);
1073 mailbox2.set_allow_overlay(false);
1074 scoped_ptr<SingleReleaseCallbackImpl> release_callback2 =
1075 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback));
1076 ResourceProvider::ResourceId id2 =
1077 child_resource_provider_->CreateResourceFromTextureMailbox(
1078 mailbox2, release_callback2.Pass());
1080 ReturnedResourceArray returned_to_child;
1081 int child_id =
1082 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1084 // Transfer some resources to the parent.
1085 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1086 resource_ids_to_transfer.push_back(id1);
1087 resource_ids_to_transfer.push_back(id2);
1088 TransferableResourceArray list;
1089 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1090 &list);
1091 ASSERT_EQ(2u, list.size());
1092 resource_provider_->ReceiveFromChild(child_id, list);
1093 EXPECT_TRUE(resource_provider_->AllowOverlay(list[0].id));
1094 EXPECT_FALSE(resource_provider_->AllowOverlay(list[1].id));
1096 resource_provider_->DeclareUsedResourcesFromChild(
1097 child_id, ResourceProvider::ResourceIdSet());
1099 EXPECT_EQ(2u, returned_to_child.size());
1100 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
1102 child_resource_provider_->DeleteResource(id1);
1103 child_resource_provider_->DeleteResource(id2);
1104 EXPECT_EQ(0u, child_resource_provider_->num_resources());
1106 resource_provider_->DestroyChild(child_id);
1109 TEST_P(ResourceProviderTest, TransferSoftwareResources) {
1110 if (GetParam() != ResourceProvider::RESOURCE_TYPE_BITMAP)
1111 return;
1113 gfx::Size size(1, 1);
1114 ResourceFormat format = RGBA_8888;
1115 size_t pixel_size = TextureSizeBytes(size, format);
1116 ASSERT_EQ(4U, pixel_size);
1118 ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource(
1119 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
1120 uint8_t data1[4] = { 1, 2, 3, 4 };
1121 child_resource_provider_->CopyToResource(id1, data1, size);
1123 ResourceProvider::ResourceId id2 = child_resource_provider_->CreateResource(
1124 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
1125 uint8_t data2[4] = { 5, 5, 5, 5 };
1126 child_resource_provider_->CopyToResource(id2, data2, size);
1128 scoped_ptr<SharedBitmap> shared_bitmap(CreateAndFillSharedBitmap(
1129 shared_bitmap_manager_.get(), gfx::Size(1, 1), 0));
1130 SharedBitmap* shared_bitmap_ptr = shared_bitmap.get();
1131 ResourceProvider::ResourceId id3 =
1132 child_resource_provider_->CreateResourceFromTextureMailbox(
1133 TextureMailbox(shared_bitmap_ptr, gfx::Size(1, 1)),
1134 SingleReleaseCallbackImpl::Create(base::Bind(
1135 &SharedBitmapReleaseCallback, base::Passed(&shared_bitmap))));
1137 ReturnedResourceArray returned_to_child;
1138 int child_id =
1139 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1141 // Transfer some resources to the parent.
1142 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1143 resource_ids_to_transfer.push_back(id1);
1144 resource_ids_to_transfer.push_back(id2);
1145 resource_ids_to_transfer.push_back(id3);
1146 TransferableResourceArray list;
1147 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1148 &list);
1149 ASSERT_EQ(3u, list.size());
1150 EXPECT_EQ(0u, list[0].mailbox_holder.sync_point);
1151 EXPECT_EQ(0u, list[1].mailbox_holder.sync_point);
1152 EXPECT_EQ(0u, list[2].mailbox_holder.sync_point);
1153 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1154 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
1155 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
1156 resource_provider_->ReceiveFromChild(child_id, list);
1157 ResourceProvider::ResourceIdSet resource_ids_to_receive;
1158 resource_ids_to_receive.insert(id1);
1159 resource_ids_to_receive.insert(id2);
1160 resource_ids_to_receive.insert(id3);
1161 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1162 resource_ids_to_receive);
1165 EXPECT_EQ(3u, resource_provider_->num_resources());
1166 ResourceProvider::ResourceIdMap resource_map =
1167 resource_provider_->GetChildToParentMap(child_id);
1168 ResourceProvider::ResourceId mapped_id1 = resource_map[id1];
1169 ResourceProvider::ResourceId mapped_id2 = resource_map[id2];
1170 ResourceProvider::ResourceId mapped_id3 = resource_map[id3];
1171 EXPECT_NE(0u, mapped_id1);
1172 EXPECT_NE(0u, mapped_id2);
1173 EXPECT_NE(0u, mapped_id3);
1174 EXPECT_FALSE(resource_provider_->InUseByConsumer(id1));
1175 EXPECT_FALSE(resource_provider_->InUseByConsumer(id2));
1176 EXPECT_FALSE(resource_provider_->InUseByConsumer(id3));
1178 uint8_t result[4] = { 0 };
1179 GetResourcePixels(
1180 resource_provider_.get(), context(), mapped_id1, size, format, result);
1181 EXPECT_EQ(0, memcmp(data1, result, pixel_size));
1183 GetResourcePixels(
1184 resource_provider_.get(), context(), mapped_id2, size, format, result);
1185 EXPECT_EQ(0, memcmp(data2, result, pixel_size));
1188 // Check that transfering again the same resource from the child to the
1189 // parent works.
1190 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1191 resource_ids_to_transfer.push_back(id1);
1192 resource_ids_to_transfer.push_back(id2);
1193 TransferableResourceArray list;
1194 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1195 &list);
1196 EXPECT_EQ(2u, list.size());
1197 EXPECT_EQ(id1, list[0].id);
1198 EXPECT_EQ(id2, list[1].id);
1199 ReturnedResourceArray returned;
1200 TransferableResource::ReturnResources(list, &returned);
1201 child_resource_provider_->ReceiveReturnsFromParent(returned);
1202 // ids were exported twice, we returned them only once, they should still
1203 // be in-use.
1204 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1205 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
1208 EXPECT_EQ(0u, returned_to_child.size());
1210 // Transfer resources back from the parent to the child. Set no resources as
1211 // being in use.
1212 ResourceProvider::ResourceIdSet no_resources;
1213 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
1215 ASSERT_EQ(3u, returned_to_child.size());
1216 EXPECT_EQ(0u, returned_to_child[0].sync_point);
1217 EXPECT_EQ(0u, returned_to_child[1].sync_point);
1218 EXPECT_EQ(0u, returned_to_child[2].sync_point);
1219 std::set<ResourceProvider::ResourceId> expected_ids;
1220 expected_ids.insert(id1);
1221 expected_ids.insert(id2);
1222 expected_ids.insert(id3);
1223 std::set<ResourceProvider::ResourceId> returned_ids;
1224 for (unsigned i = 0; i < 3; i++)
1225 returned_ids.insert(returned_to_child[i].id);
1226 EXPECT_EQ(expected_ids, returned_ids);
1227 EXPECT_FALSE(returned_to_child[0].lost);
1228 EXPECT_FALSE(returned_to_child[1].lost);
1229 EXPECT_FALSE(returned_to_child[2].lost);
1230 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
1231 returned_to_child.clear();
1233 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id1));
1234 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id2));
1235 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id3));
1238 ResourceProvider::ScopedReadLockSoftware lock(
1239 child_resource_provider_.get(), id1);
1240 const SkBitmap* sk_bitmap = lock.sk_bitmap();
1241 EXPECT_EQ(sk_bitmap->width(), size.width());
1242 EXPECT_EQ(sk_bitmap->height(), size.height());
1243 EXPECT_EQ(0, memcmp(data1, sk_bitmap->getPixels(), pixel_size));
1246 ResourceProvider::ScopedReadLockSoftware lock(
1247 child_resource_provider_.get(), id2);
1248 const SkBitmap* sk_bitmap = lock.sk_bitmap();
1249 EXPECT_EQ(sk_bitmap->width(), size.width());
1250 EXPECT_EQ(sk_bitmap->height(), size.height());
1251 EXPECT_EQ(0, memcmp(data2, sk_bitmap->getPixels(), pixel_size));
1254 // Transfer resources to the parent again.
1255 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1256 resource_ids_to_transfer.push_back(id1);
1257 resource_ids_to_transfer.push_back(id2);
1258 resource_ids_to_transfer.push_back(id3);
1259 TransferableResourceArray list;
1260 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1261 &list);
1262 ASSERT_EQ(3u, list.size());
1263 EXPECT_EQ(id1, list[0].id);
1264 EXPECT_EQ(id2, list[1].id);
1265 EXPECT_EQ(id3, list[2].id);
1266 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1267 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
1268 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
1269 resource_provider_->ReceiveFromChild(child_id, list);
1270 ResourceProvider::ResourceIdSet resource_ids_to_receive;
1271 resource_ids_to_receive.insert(id1);
1272 resource_ids_to_receive.insert(id2);
1273 resource_ids_to_receive.insert(id3);
1274 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1275 resource_ids_to_receive);
1278 EXPECT_EQ(0u, returned_to_child.size());
1280 EXPECT_EQ(3u, resource_provider_->num_resources());
1281 resource_provider_->DestroyChild(child_id);
1282 EXPECT_EQ(0u, resource_provider_->num_resources());
1284 ASSERT_EQ(3u, returned_to_child.size());
1285 EXPECT_EQ(0u, returned_to_child[0].sync_point);
1286 EXPECT_EQ(0u, returned_to_child[1].sync_point);
1287 EXPECT_EQ(0u, returned_to_child[2].sync_point);
1288 std::set<ResourceProvider::ResourceId> expected_ids;
1289 expected_ids.insert(id1);
1290 expected_ids.insert(id2);
1291 expected_ids.insert(id3);
1292 std::set<ResourceProvider::ResourceId> returned_ids;
1293 for (unsigned i = 0; i < 3; i++)
1294 returned_ids.insert(returned_to_child[i].id);
1295 EXPECT_EQ(expected_ids, returned_ids);
1296 EXPECT_FALSE(returned_to_child[0].lost);
1297 EXPECT_FALSE(returned_to_child[1].lost);
1298 EXPECT_FALSE(returned_to_child[2].lost);
1301 TEST_P(ResourceProviderTest, TransferGLToSoftware) {
1302 if (GetParam() != ResourceProvider::RESOURCE_TYPE_BITMAP)
1303 return;
1305 scoped_ptr<ResourceProviderContext> child_context_owned(
1306 ResourceProviderContext::Create(shared_data_.get()));
1308 FakeOutputSurfaceClient child_output_surface_client;
1309 scoped_ptr<OutputSurface> child_output_surface(
1310 FakeOutputSurface::Create3d(child_context_owned.Pass()));
1311 CHECK(child_output_surface->BindToClient(&child_output_surface_client));
1313 scoped_ptr<ResourceProvider> child_resource_provider(
1314 ResourceProvider::Create(child_output_surface.get(),
1315 shared_bitmap_manager_.get(),
1316 gpu_memory_buffer_manager_.get(),
1317 NULL,
1319 false,
1320 1));
1322 gfx::Size size(1, 1);
1323 ResourceFormat format = RGBA_8888;
1324 size_t pixel_size = TextureSizeBytes(size, format);
1325 ASSERT_EQ(4U, pixel_size);
1327 ResourceProvider::ResourceId id1 = child_resource_provider->CreateResource(
1328 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
1329 uint8_t data1[4] = { 1, 2, 3, 4 };
1330 child_resource_provider->CopyToResource(id1, data1, size);
1332 ReturnedResourceArray returned_to_child;
1333 int child_id =
1334 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1336 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1337 resource_ids_to_transfer.push_back(id1);
1338 TransferableResourceArray list;
1339 child_resource_provider->PrepareSendToParent(resource_ids_to_transfer,
1340 &list);
1341 ASSERT_EQ(1u, list.size());
1342 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
1343 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
1344 list[0].mailbox_holder.texture_target);
1345 EXPECT_TRUE(child_resource_provider->InUseByConsumer(id1));
1346 resource_provider_->ReceiveFromChild(child_id, list);
1349 EXPECT_EQ(0u, resource_provider_->num_resources());
1350 ASSERT_EQ(1u, returned_to_child.size());
1351 EXPECT_EQ(returned_to_child[0].id, id1);
1352 ResourceProvider::ResourceIdMap resource_map =
1353 resource_provider_->GetChildToParentMap(child_id);
1354 ResourceProvider::ResourceId mapped_id1 = resource_map[id1];
1355 EXPECT_EQ(0u, mapped_id1);
1357 resource_provider_->DestroyChild(child_id);
1358 EXPECT_EQ(0u, resource_provider_->num_resources());
1360 ASSERT_EQ(1u, returned_to_child.size());
1361 EXPECT_FALSE(returned_to_child[0].lost);
1364 TEST_P(ResourceProviderTest, TransferInvalidSoftware) {
1365 if (GetParam() != ResourceProvider::RESOURCE_TYPE_BITMAP)
1366 return;
1368 gfx::Size size(1, 1);
1369 ResourceFormat format = RGBA_8888;
1370 size_t pixel_size = TextureSizeBytes(size, format);
1371 ASSERT_EQ(4U, pixel_size);
1373 ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource(
1374 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
1375 uint8_t data1[4] = { 1, 2, 3, 4 };
1376 child_resource_provider_->CopyToResource(id1, data1, size);
1378 ReturnedResourceArray returned_to_child;
1379 int child_id =
1380 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1382 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1383 resource_ids_to_transfer.push_back(id1);
1384 TransferableResourceArray list;
1385 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1386 &list);
1387 ASSERT_EQ(1u, list.size());
1388 // Make invalid.
1389 list[0].mailbox_holder.mailbox.name[1] = 5;
1390 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1391 resource_provider_->ReceiveFromChild(child_id, list);
1394 EXPECT_EQ(1u, resource_provider_->num_resources());
1395 EXPECT_EQ(0u, returned_to_child.size());
1397 ResourceProvider::ResourceIdMap resource_map =
1398 resource_provider_->GetChildToParentMap(child_id);
1399 ResourceProvider::ResourceId mapped_id1 = resource_map[id1];
1400 EXPECT_NE(0u, mapped_id1);
1402 ResourceProvider::ScopedReadLockSoftware lock(resource_provider_.get(),
1403 mapped_id1);
1404 EXPECT_FALSE(lock.valid());
1407 resource_provider_->DestroyChild(child_id);
1408 EXPECT_EQ(0u, resource_provider_->num_resources());
1410 ASSERT_EQ(1u, returned_to_child.size());
1411 EXPECT_FALSE(returned_to_child[0].lost);
1414 TEST_P(ResourceProviderTest, DeleteExportedResources) {
1415 gfx::Size size(1, 1);
1416 ResourceFormat format = RGBA_8888;
1417 size_t pixel_size = TextureSizeBytes(size, format);
1418 ASSERT_EQ(4U, pixel_size);
1420 ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource(
1421 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
1422 uint8_t data1[4] = { 1, 2, 3, 4 };
1423 child_resource_provider_->CopyToResource(id1, data1, size);
1425 ResourceProvider::ResourceId id2 = child_resource_provider_->CreateResource(
1426 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
1427 uint8_t data2[4] = {5, 5, 5, 5};
1428 child_resource_provider_->CopyToResource(id2, data2, size);
1430 ReturnedResourceArray returned_to_child;
1431 int child_id =
1432 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1434 // Transfer some resources to the parent.
1435 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1436 resource_ids_to_transfer.push_back(id1);
1437 resource_ids_to_transfer.push_back(id2);
1438 TransferableResourceArray list;
1439 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1440 &list);
1441 ASSERT_EQ(2u, list.size());
1442 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) {
1443 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
1444 EXPECT_NE(0u, list[1].mailbox_holder.sync_point);
1446 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1447 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
1448 resource_provider_->ReceiveFromChild(child_id, list);
1449 ResourceProvider::ResourceIdSet resource_ids_to_receive;
1450 resource_ids_to_receive.insert(id1);
1451 resource_ids_to_receive.insert(id2);
1452 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1453 resource_ids_to_receive);
1456 EXPECT_EQ(2u, resource_provider_->num_resources());
1457 ResourceProvider::ResourceIdMap resource_map =
1458 resource_provider_->GetChildToParentMap(child_id);
1459 ResourceProvider::ResourceId mapped_id1 = resource_map[id1];
1460 ResourceProvider::ResourceId mapped_id2 = resource_map[id2];
1461 EXPECT_NE(0u, mapped_id1);
1462 EXPECT_NE(0u, mapped_id2);
1463 EXPECT_FALSE(resource_provider_->InUseByConsumer(id1));
1464 EXPECT_FALSE(resource_provider_->InUseByConsumer(id2));
1467 // The parent transfers the resources to the grandparent.
1468 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1469 resource_ids_to_transfer.push_back(mapped_id1);
1470 resource_ids_to_transfer.push_back(mapped_id2);
1471 TransferableResourceArray list;
1472 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
1474 ASSERT_EQ(2u, list.size());
1475 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) {
1476 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
1477 EXPECT_NE(0u, list[1].mailbox_holder.sync_point);
1479 EXPECT_TRUE(resource_provider_->InUseByConsumer(id1));
1480 EXPECT_TRUE(resource_provider_->InUseByConsumer(id2));
1482 // Release the resource in the parent. Set no resources as being in use. The
1483 // resources are exported so that can't be transferred back yet.
1484 ResourceProvider::ResourceIdSet no_resources;
1485 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
1487 EXPECT_EQ(0u, returned_to_child.size());
1488 EXPECT_EQ(2u, resource_provider_->num_resources());
1490 // Return the resources from the grandparent to the parent. They should be
1491 // returned to the child then.
1492 EXPECT_EQ(2u, list.size());
1493 EXPECT_EQ(mapped_id1, list[0].id);
1494 EXPECT_EQ(mapped_id2, list[1].id);
1495 ReturnedResourceArray returned;
1496 TransferableResource::ReturnResources(list, &returned);
1497 resource_provider_->ReceiveReturnsFromParent(returned);
1499 EXPECT_EQ(0u, resource_provider_->num_resources());
1500 ASSERT_EQ(2u, returned_to_child.size());
1501 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) {
1502 EXPECT_NE(0u, returned_to_child[0].sync_point);
1503 EXPECT_NE(0u, returned_to_child[1].sync_point);
1505 EXPECT_FALSE(returned_to_child[0].lost);
1506 EXPECT_FALSE(returned_to_child[1].lost);
1510 TEST_P(ResourceProviderTest, DestroyChildWithExportedResources) {
1511 gfx::Size size(1, 1);
1512 ResourceFormat format = RGBA_8888;
1513 size_t pixel_size = TextureSizeBytes(size, format);
1514 ASSERT_EQ(4U, pixel_size);
1516 ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource(
1517 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
1518 uint8_t data1[4] = {1, 2, 3, 4};
1519 child_resource_provider_->CopyToResource(id1, data1, size);
1521 ResourceProvider::ResourceId id2 = child_resource_provider_->CreateResource(
1522 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
1523 uint8_t data2[4] = {5, 5, 5, 5};
1524 child_resource_provider_->CopyToResource(id2, data2, size);
1526 ReturnedResourceArray returned_to_child;
1527 int child_id =
1528 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1530 // Transfer some resources to the parent.
1531 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1532 resource_ids_to_transfer.push_back(id1);
1533 resource_ids_to_transfer.push_back(id2);
1534 TransferableResourceArray list;
1535 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1536 &list);
1537 ASSERT_EQ(2u, list.size());
1538 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) {
1539 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
1540 EXPECT_NE(0u, list[1].mailbox_holder.sync_point);
1542 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1543 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
1544 resource_provider_->ReceiveFromChild(child_id, list);
1545 ResourceProvider::ResourceIdSet resource_ids_to_receive;
1546 resource_ids_to_receive.insert(id1);
1547 resource_ids_to_receive.insert(id2);
1548 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1549 resource_ids_to_receive);
1552 EXPECT_EQ(2u, resource_provider_->num_resources());
1553 ResourceProvider::ResourceIdMap resource_map =
1554 resource_provider_->GetChildToParentMap(child_id);
1555 ResourceProvider::ResourceId mapped_id1 = resource_map[id1];
1556 ResourceProvider::ResourceId mapped_id2 = resource_map[id2];
1557 EXPECT_NE(0u, mapped_id1);
1558 EXPECT_NE(0u, mapped_id2);
1559 EXPECT_FALSE(resource_provider_->InUseByConsumer(id1));
1560 EXPECT_FALSE(resource_provider_->InUseByConsumer(id2));
1563 // The parent transfers the resources to the grandparent.
1564 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1565 resource_ids_to_transfer.push_back(mapped_id1);
1566 resource_ids_to_transfer.push_back(mapped_id2);
1567 TransferableResourceArray list;
1568 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
1570 ASSERT_EQ(2u, list.size());
1571 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) {
1572 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
1573 EXPECT_NE(0u, list[1].mailbox_holder.sync_point);
1575 EXPECT_TRUE(resource_provider_->InUseByConsumer(id1));
1576 EXPECT_TRUE(resource_provider_->InUseByConsumer(id2));
1578 // Release the resource in the parent. Set no resources as being in use. The
1579 // resources are exported so that can't be transferred back yet.
1580 ResourceProvider::ResourceIdSet no_resources;
1581 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
1583 // Destroy the child, the resources should not be returned yet.
1584 EXPECT_EQ(0u, returned_to_child.size());
1585 EXPECT_EQ(2u, resource_provider_->num_resources());
1587 resource_provider_->DestroyChild(child_id);
1589 EXPECT_EQ(2u, resource_provider_->num_resources());
1590 ASSERT_EQ(0u, returned_to_child.size());
1592 // Return a resource from the grandparent, it should be returned at this
1593 // point.
1594 EXPECT_EQ(2u, list.size());
1595 EXPECT_EQ(mapped_id1, list[0].id);
1596 EXPECT_EQ(mapped_id2, list[1].id);
1597 TransferableResourceArray return_list;
1598 return_list.push_back(list[1]);
1599 list.pop_back();
1600 ReturnedResourceArray returned;
1601 TransferableResource::ReturnResources(return_list, &returned);
1602 resource_provider_->ReceiveReturnsFromParent(returned);
1604 EXPECT_EQ(1u, resource_provider_->num_resources());
1605 ASSERT_EQ(1u, returned_to_child.size());
1606 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) {
1607 EXPECT_NE(0u, returned_to_child[0].sync_point);
1609 EXPECT_FALSE(returned_to_child[0].lost);
1610 returned_to_child.clear();
1612 // Destroy the parent resource provider. The resource that's left should be
1613 // lost at this point, and returned.
1614 resource_provider_ = nullptr;
1615 ASSERT_EQ(1u, returned_to_child.size());
1616 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) {
1617 EXPECT_NE(0u, returned_to_child[0].sync_point);
1619 EXPECT_TRUE(returned_to_child[0].lost);
1623 TEST_P(ResourceProviderTest, DeleteTransferredResources) {
1624 gfx::Size size(1, 1);
1625 ResourceFormat format = RGBA_8888;
1626 size_t pixel_size = TextureSizeBytes(size, format);
1627 ASSERT_EQ(4U, pixel_size);
1629 ResourceProvider::ResourceId id = child_resource_provider_->CreateResource(
1630 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
1631 uint8_t data[4] = { 1, 2, 3, 4 };
1632 child_resource_provider_->CopyToResource(id, data, size);
1634 ReturnedResourceArray returned_to_child;
1635 int child_id =
1636 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1638 // Transfer some resource to the parent.
1639 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1640 resource_ids_to_transfer.push_back(id);
1641 TransferableResourceArray list;
1642 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1643 &list);
1644 ASSERT_EQ(1u, list.size());
1645 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
1646 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
1647 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id));
1648 resource_provider_->ReceiveFromChild(child_id, list);
1649 ResourceProvider::ResourceIdSet resource_ids_to_receive;
1650 resource_ids_to_receive.insert(id);
1651 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1652 resource_ids_to_receive);
1655 // Delete textures in the child, while they are transfered.
1656 child_resource_provider_->DeleteResource(id);
1657 EXPECT_EQ(1u, child_resource_provider_->num_resources());
1659 EXPECT_EQ(0u, returned_to_child.size());
1661 // Transfer resources back from the parent to the child. Set no resources as
1662 // being in use.
1663 ResourceProvider::ResourceIdSet no_resources;
1664 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
1666 ASSERT_EQ(1u, returned_to_child.size());
1667 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
1668 EXPECT_NE(0u, returned_to_child[0].sync_point);
1669 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
1671 EXPECT_EQ(0u, child_resource_provider_->num_resources());
1674 TEST_P(ResourceProviderTest, UnuseTransferredResources) {
1675 gfx::Size size(1, 1);
1676 ResourceFormat format = RGBA_8888;
1677 size_t pixel_size = TextureSizeBytes(size, format);
1678 ASSERT_EQ(4U, pixel_size);
1680 ResourceProvider::ResourceId id = child_resource_provider_->CreateResource(
1681 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
1682 uint8_t data[4] = {1, 2, 3, 4};
1683 child_resource_provider_->CopyToResource(id, data, size);
1685 ReturnedResourceArray returned_to_child;
1686 int child_id =
1687 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1688 const ResourceProvider::ResourceIdMap& map =
1689 resource_provider_->GetChildToParentMap(child_id);
1691 // Transfer some resource to the parent.
1692 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1693 resource_ids_to_transfer.push_back(id);
1694 TransferableResourceArray list;
1695 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1696 &list);
1697 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id));
1698 resource_provider_->ReceiveFromChild(child_id, list);
1699 ResourceProvider::ResourceIdSet resource_ids_to_receive;
1700 resource_ids_to_receive.insert(id);
1701 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1702 resource_ids_to_receive);
1704 TransferableResourceArray sent_to_top_level;
1706 // Parent transfers to top-level.
1707 ASSERT_TRUE(map.find(id) != map.end());
1708 ResourceProvider::ResourceId parent_id = map.find(id)->second;
1709 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1710 resource_ids_to_transfer.push_back(parent_id);
1711 resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1712 &sent_to_top_level);
1713 EXPECT_TRUE(resource_provider_->InUseByConsumer(parent_id));
1716 // Stop using resource.
1717 ResourceProvider::ResourceIdSet empty;
1718 resource_provider_->DeclareUsedResourcesFromChild(child_id, empty);
1719 // Resource is not yet returned to the child, since it's in use by the
1720 // top-level.
1721 EXPECT_TRUE(returned_to_child.empty());
1724 // Send the resource to the parent again.
1725 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1726 resource_ids_to_transfer.push_back(id);
1727 TransferableResourceArray list;
1728 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1729 &list);
1730 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id));
1731 resource_provider_->ReceiveFromChild(child_id, list);
1732 ResourceProvider::ResourceIdSet resource_ids_to_receive;
1733 resource_ids_to_receive.insert(id);
1734 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1735 resource_ids_to_receive);
1738 // Receive returns back from top-level.
1739 ReturnedResourceArray returned;
1740 TransferableResource::ReturnResources(sent_to_top_level, &returned);
1741 resource_provider_->ReceiveReturnsFromParent(returned);
1742 // Resource is still not yet returned to the child, since it's declared used
1743 // in the parent.
1744 EXPECT_TRUE(returned_to_child.empty());
1745 ASSERT_TRUE(map.find(id) != map.end());
1746 ResourceProvider::ResourceId parent_id = map.find(id)->second;
1747 EXPECT_FALSE(resource_provider_->InUseByConsumer(parent_id));
1750 sent_to_top_level.clear();
1751 // Parent transfers again to top-level.
1752 ASSERT_TRUE(map.find(id) != map.end());
1753 ResourceProvider::ResourceId parent_id = map.find(id)->second;
1754 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1755 resource_ids_to_transfer.push_back(parent_id);
1756 resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1757 &sent_to_top_level);
1758 EXPECT_TRUE(resource_provider_->InUseByConsumer(parent_id));
1761 // Receive returns back from top-level.
1762 ReturnedResourceArray returned;
1763 TransferableResource::ReturnResources(sent_to_top_level, &returned);
1764 resource_provider_->ReceiveReturnsFromParent(returned);
1765 // Resource is still not yet returned to the child, since it's still
1766 // declared used in the parent.
1767 EXPECT_TRUE(returned_to_child.empty());
1768 ASSERT_TRUE(map.find(id) != map.end());
1769 ResourceProvider::ResourceId parent_id = map.find(id)->second;
1770 EXPECT_FALSE(resource_provider_->InUseByConsumer(parent_id));
1773 // Stop using resource.
1774 ResourceProvider::ResourceIdSet empty;
1775 resource_provider_->DeclareUsedResourcesFromChild(child_id, empty);
1776 // Resource should have been returned to the child, since it's no longer in
1777 // use by the top-level.
1778 ASSERT_EQ(1u, returned_to_child.size());
1779 EXPECT_EQ(id, returned_to_child[0].id);
1780 EXPECT_EQ(2, returned_to_child[0].count);
1781 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
1782 returned_to_child.clear();
1783 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id));
1787 class ResourceProviderTestTextureFilters : public ResourceProviderTest {
1788 public:
1789 static void RunTest(GLenum child_filter, GLenum parent_filter) {
1790 scoped_ptr<TextureStateTrackingContext> child_context_owned(
1791 new TextureStateTrackingContext);
1792 TextureStateTrackingContext* child_context = child_context_owned.get();
1794 FakeOutputSurfaceClient child_output_surface_client;
1795 scoped_ptr<OutputSurface> child_output_surface(
1796 FakeOutputSurface::Create3d(child_context_owned.Pass()));
1797 CHECK(child_output_surface->BindToClient(&child_output_surface_client));
1798 scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
1799 new TestSharedBitmapManager());
1801 scoped_ptr<ResourceProvider> child_resource_provider(
1802 ResourceProvider::Create(child_output_surface.get(),
1803 shared_bitmap_manager.get(),
1804 NULL,
1805 NULL,
1807 false,
1808 1));
1810 scoped_ptr<TextureStateTrackingContext> parent_context_owned(
1811 new TextureStateTrackingContext);
1812 TextureStateTrackingContext* parent_context = parent_context_owned.get();
1814 FakeOutputSurfaceClient parent_output_surface_client;
1815 scoped_ptr<OutputSurface> parent_output_surface(
1816 FakeOutputSurface::Create3d(parent_context_owned.Pass()));
1817 CHECK(parent_output_surface->BindToClient(&parent_output_surface_client));
1819 scoped_ptr<ResourceProvider> parent_resource_provider(
1820 ResourceProvider::Create(parent_output_surface.get(),
1821 shared_bitmap_manager.get(),
1822 NULL,
1823 NULL,
1825 false,
1826 1));
1828 gfx::Size size(1, 1);
1829 ResourceFormat format = RGBA_8888;
1830 int child_texture_id = 1;
1831 int parent_texture_id = 2;
1833 size_t pixel_size = TextureSizeBytes(size, format);
1834 ASSERT_EQ(4U, pixel_size);
1836 ResourceProvider::ResourceId id = child_resource_provider->CreateResource(
1837 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE,
1838 format);
1840 // The new texture is created with GL_LINEAR.
1841 EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, child_texture_id))
1842 .Times(2); // Once to create and once to allocate.
1843 EXPECT_CALL(*child_context,
1844 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
1845 EXPECT_CALL(*child_context,
1846 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
1847 EXPECT_CALL(
1848 *child_context,
1849 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
1850 EXPECT_CALL(
1851 *child_context,
1852 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
1853 EXPECT_CALL(*child_context,
1854 texParameteri(GL_TEXTURE_2D,
1855 GL_TEXTURE_POOL_CHROMIUM,
1856 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM));
1857 child_resource_provider->AllocateForTesting(id);
1858 Mock::VerifyAndClearExpectations(child_context);
1860 uint8_t data[4] = { 1, 2, 3, 4 };
1862 EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, child_texture_id));
1863 child_resource_provider->CopyToResource(id, data, size);
1864 Mock::VerifyAndClearExpectations(child_context);
1866 // The texture is set to |child_filter| in the child.
1867 EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, child_texture_id));
1868 if (child_filter != GL_LINEAR) {
1869 EXPECT_CALL(
1870 *child_context,
1871 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, child_filter));
1872 EXPECT_CALL(
1873 *child_context,
1874 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, child_filter));
1876 SetResourceFilter(child_resource_provider.get(), id, child_filter);
1877 Mock::VerifyAndClearExpectations(child_context);
1879 ReturnedResourceArray returned_to_child;
1880 int child_id = parent_resource_provider->CreateChild(
1881 GetReturnCallback(&returned_to_child));
1883 // Transfer some resource to the parent.
1884 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1885 resource_ids_to_transfer.push_back(id);
1886 TransferableResourceArray list;
1888 EXPECT_CALL(*child_context,
1889 produceTextureDirectCHROMIUM(_, GL_TEXTURE_2D, _));
1890 EXPECT_CALL(*child_context, insertSyncPoint());
1891 child_resource_provider->PrepareSendToParent(resource_ids_to_transfer,
1892 &list);
1893 Mock::VerifyAndClearExpectations(child_context);
1895 ASSERT_EQ(1u, list.size());
1896 EXPECT_EQ(static_cast<unsigned>(child_filter), list[0].filter);
1898 EXPECT_CALL(*parent_context,
1899 createAndConsumeTextureCHROMIUM(GL_TEXTURE_2D, _))
1900 .WillOnce(Return(parent_texture_id));
1902 parent_resource_provider->ReceiveFromChild(child_id, list);
1904 parent_resource_provider->WaitSyncPointIfNeeded(list[0].id);
1905 ResourceProvider::ScopedReadLockGL lock(parent_resource_provider.get(),
1906 list[0].id);
1908 Mock::VerifyAndClearExpectations(parent_context);
1910 ResourceProvider::ResourceIdSet resource_ids_to_receive;
1911 resource_ids_to_receive.insert(id);
1912 parent_resource_provider->DeclareUsedResourcesFromChild(
1913 child_id, resource_ids_to_receive);
1914 Mock::VerifyAndClearExpectations(parent_context);
1916 ResourceProvider::ResourceIdMap resource_map =
1917 parent_resource_provider->GetChildToParentMap(child_id);
1918 ResourceProvider::ResourceId mapped_id = resource_map[id];
1919 EXPECT_NE(0u, mapped_id);
1921 // The texture is set to |parent_filter| in the parent.
1922 EXPECT_CALL(*parent_context, bindTexture(GL_TEXTURE_2D, parent_texture_id));
1923 EXPECT_CALL(
1924 *parent_context,
1925 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, parent_filter));
1926 EXPECT_CALL(
1927 *parent_context,
1928 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, parent_filter));
1929 SetResourceFilter(parent_resource_provider.get(), mapped_id, parent_filter);
1930 Mock::VerifyAndClearExpectations(parent_context);
1932 // The texture should be reset to |child_filter| in the parent when it is
1933 // returned, since that is how it was received.
1934 EXPECT_CALL(*parent_context, bindTexture(GL_TEXTURE_2D, parent_texture_id));
1935 EXPECT_CALL(
1936 *parent_context,
1937 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, child_filter));
1938 EXPECT_CALL(
1939 *parent_context,
1940 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, child_filter));
1943 EXPECT_EQ(0u, returned_to_child.size());
1945 // Transfer resources back from the parent to the child. Set no resources
1946 // as being in use.
1947 ResourceProvider::ResourceIdSet no_resources;
1948 EXPECT_CALL(*parent_context, insertSyncPoint());
1949 parent_resource_provider->DeclareUsedResourcesFromChild(child_id,
1950 no_resources);
1951 Mock::VerifyAndClearExpectations(parent_context);
1953 ASSERT_EQ(1u, returned_to_child.size());
1954 child_resource_provider->ReceiveReturnsFromParent(returned_to_child);
1957 // The child remembers the texture filter is set to |child_filter|.
1958 EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, child_texture_id));
1959 SetResourceFilter(child_resource_provider.get(), id, child_filter);
1960 Mock::VerifyAndClearExpectations(child_context);
1964 TEST_P(ResourceProviderTest, TextureFilters_ChildNearestParentLinear) {
1965 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
1966 return;
1967 ResourceProviderTestTextureFilters::RunTest(GL_NEAREST, GL_LINEAR);
1970 TEST_P(ResourceProviderTest, TextureFilters_ChildLinearParentNearest) {
1971 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
1972 return;
1973 ResourceProviderTestTextureFilters::RunTest(GL_LINEAR, GL_NEAREST);
1976 TEST_P(ResourceProviderTest, TransferMailboxResources) {
1977 // Other mailbox transfers tested elsewhere.
1978 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
1979 return;
1980 unsigned texture = context()->createTexture();
1981 context()->bindTexture(GL_TEXTURE_2D, texture);
1982 uint8_t data[4] = { 1, 2, 3, 4 };
1983 context()->texImage2D(
1984 GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &data);
1985 gpu::Mailbox mailbox;
1986 context()->genMailboxCHROMIUM(mailbox.name);
1987 context()->produceTextureDirectCHROMIUM(texture, GL_TEXTURE_2D, mailbox.name);
1988 uint32 sync_point = context()->insertSyncPoint();
1990 // All the logic below assumes that the sync points are all positive.
1991 EXPECT_LT(0u, sync_point);
1993 uint32 release_sync_point = 0;
1994 bool lost_resource = false;
1995 BlockingTaskRunner* main_thread_task_runner = NULL;
1996 ReleaseCallbackImpl callback = base::Bind(ReleaseCallback,
1997 &release_sync_point,
1998 &lost_resource,
1999 &main_thread_task_runner);
2000 ResourceProvider::ResourceId resource =
2001 resource_provider_->CreateResourceFromTextureMailbox(
2002 TextureMailbox(mailbox, GL_TEXTURE_2D, sync_point),
2003 SingleReleaseCallbackImpl::Create(callback));
2004 EXPECT_EQ(1u, context()->NumTextures());
2005 EXPECT_EQ(0u, release_sync_point);
2007 // Transfer the resource, expect the sync points to be consistent.
2008 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2009 resource_ids_to_transfer.push_back(resource);
2010 TransferableResourceArray list;
2011 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
2012 ASSERT_EQ(1u, list.size());
2013 EXPECT_LE(sync_point, list[0].mailbox_holder.sync_point);
2014 EXPECT_EQ(0,
2015 memcmp(mailbox.name,
2016 list[0].mailbox_holder.mailbox.name,
2017 sizeof(mailbox.name)));
2018 EXPECT_EQ(0u, release_sync_point);
2020 context()->waitSyncPoint(list[0].mailbox_holder.sync_point);
2021 unsigned other_texture =
2022 context()->createAndConsumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
2023 uint8_t test_data[4] = { 0 };
2024 context()->GetPixels(
2025 gfx::Size(1, 1), RGBA_8888, test_data);
2026 EXPECT_EQ(0, memcmp(data, test_data, sizeof(data)));
2028 context()->produceTextureDirectCHROMIUM(other_texture, GL_TEXTURE_2D,
2029 mailbox.name);
2030 context()->deleteTexture(other_texture);
2031 list[0].mailbox_holder.sync_point = context()->insertSyncPoint();
2032 EXPECT_LT(0u, list[0].mailbox_holder.sync_point);
2034 // Receive the resource, then delete it, expect the sync points to be
2035 // consistent.
2036 ReturnedResourceArray returned;
2037 TransferableResource::ReturnResources(list, &returned);
2038 resource_provider_->ReceiveReturnsFromParent(returned);
2039 EXPECT_EQ(1u, context()->NumTextures());
2040 EXPECT_EQ(0u, release_sync_point);
2042 resource_provider_->DeleteResource(resource);
2043 EXPECT_LE(list[0].mailbox_holder.sync_point, release_sync_point);
2044 EXPECT_FALSE(lost_resource);
2045 EXPECT_EQ(main_thread_task_runner_.get(), main_thread_task_runner);
2048 // We're going to do the same thing as above, but testing the case where we
2049 // delete the resource before we receive it back.
2050 sync_point = release_sync_point;
2051 EXPECT_LT(0u, sync_point);
2052 release_sync_point = 0;
2053 resource = resource_provider_->CreateResourceFromTextureMailbox(
2054 TextureMailbox(mailbox, GL_TEXTURE_2D, sync_point),
2055 SingleReleaseCallbackImpl::Create(callback));
2056 EXPECT_EQ(1u, context()->NumTextures());
2057 EXPECT_EQ(0u, release_sync_point);
2059 // Transfer the resource, expect the sync points to be consistent.
2060 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2061 resource_ids_to_transfer.push_back(resource);
2062 TransferableResourceArray list;
2063 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
2064 ASSERT_EQ(1u, list.size());
2065 EXPECT_LE(sync_point, list[0].mailbox_holder.sync_point);
2066 EXPECT_EQ(0,
2067 memcmp(mailbox.name,
2068 list[0].mailbox_holder.mailbox.name,
2069 sizeof(mailbox.name)));
2070 EXPECT_EQ(0u, release_sync_point);
2072 context()->waitSyncPoint(list[0].mailbox_holder.sync_point);
2073 unsigned other_texture =
2074 context()->createAndConsumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
2075 uint8_t test_data[4] = { 0 };
2076 context()->GetPixels(
2077 gfx::Size(1, 1), RGBA_8888, test_data);
2078 EXPECT_EQ(0, memcmp(data, test_data, sizeof(data)));
2080 context()->produceTextureDirectCHROMIUM(other_texture, GL_TEXTURE_2D,
2081 mailbox.name);
2082 context()->deleteTexture(other_texture);
2083 list[0].mailbox_holder.sync_point = context()->insertSyncPoint();
2084 EXPECT_LT(0u, list[0].mailbox_holder.sync_point);
2086 // Delete the resource, which shouldn't do anything.
2087 resource_provider_->DeleteResource(resource);
2088 EXPECT_EQ(1u, context()->NumTextures());
2089 EXPECT_EQ(0u, release_sync_point);
2091 // Then receive the resource which should release the mailbox, expect the
2092 // sync points to be consistent.
2093 ReturnedResourceArray returned;
2094 TransferableResource::ReturnResources(list, &returned);
2095 resource_provider_->ReceiveReturnsFromParent(returned);
2096 EXPECT_LE(list[0].mailbox_holder.sync_point, release_sync_point);
2097 EXPECT_FALSE(lost_resource);
2098 EXPECT_EQ(main_thread_task_runner_.get(), main_thread_task_runner);
2101 context()->waitSyncPoint(release_sync_point);
2102 texture =
2103 context()->createAndConsumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
2104 context()->deleteTexture(texture);
2107 TEST_P(ResourceProviderTest, LostResourceInParent) {
2108 gfx::Size size(1, 1);
2109 ResourceFormat format = RGBA_8888;
2110 ResourceProvider::ResourceId resource =
2111 child_resource_provider_->CreateResource(
2112 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE,
2113 format);
2114 child_resource_provider_->AllocateForTesting(resource);
2115 // Expect a GL resource to be lost.
2116 bool should_lose_resource =
2117 GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE;
2119 ReturnedResourceArray returned_to_child;
2120 int child_id =
2121 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
2123 // Transfer the resource to the parent.
2124 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2125 resource_ids_to_transfer.push_back(resource);
2126 TransferableResourceArray list;
2127 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
2128 &list);
2129 EXPECT_EQ(1u, list.size());
2131 resource_provider_->ReceiveFromChild(child_id, list);
2132 ResourceProvider::ResourceIdSet resource_ids_to_receive;
2133 resource_ids_to_receive.insert(resource);
2134 resource_provider_->DeclareUsedResourcesFromChild(child_id,
2135 resource_ids_to_receive);
2138 // Lose the output surface in the parent.
2139 resource_provider_->DidLoseOutputSurface();
2142 EXPECT_EQ(0u, returned_to_child.size());
2144 // Transfer resources back from the parent to the child. Set no resources as
2145 // being in use.
2146 ResourceProvider::ResourceIdSet no_resources;
2147 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
2149 // Expect a GL resource to be lost.
2150 ASSERT_EQ(1u, returned_to_child.size());
2151 EXPECT_EQ(should_lose_resource, returned_to_child[0].lost);
2152 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
2153 returned_to_child.clear();
2156 // A GL resource should be lost.
2157 EXPECT_EQ(should_lose_resource, child_resource_provider_->IsLost(resource));
2159 // Lost resources stay in use in the parent forever.
2160 EXPECT_EQ(should_lose_resource,
2161 child_resource_provider_->InUseByConsumer(resource));
2164 TEST_P(ResourceProviderTest, LostResourceInGrandParent) {
2165 gfx::Size size(1, 1);
2166 ResourceFormat format = RGBA_8888;
2167 ResourceProvider::ResourceId resource =
2168 child_resource_provider_->CreateResource(
2169 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE,
2170 format);
2171 child_resource_provider_->AllocateForTesting(resource);
2173 ReturnedResourceArray returned_to_child;
2174 int child_id =
2175 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
2177 // Transfer the resource to the parent.
2178 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2179 resource_ids_to_transfer.push_back(resource);
2180 TransferableResourceArray list;
2181 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
2182 &list);
2183 EXPECT_EQ(1u, list.size());
2185 resource_provider_->ReceiveFromChild(child_id, list);
2186 ResourceProvider::ResourceIdSet resource_ids_to_receive;
2187 resource_ids_to_receive.insert(resource);
2188 resource_provider_->DeclareUsedResourcesFromChild(child_id,
2189 resource_ids_to_receive);
2193 ResourceProvider::ResourceIdMap resource_map =
2194 resource_provider_->GetChildToParentMap(child_id);
2195 ResourceProvider::ResourceId parent_resource = resource_map[resource];
2196 EXPECT_NE(0u, parent_resource);
2198 // Transfer to a grandparent.
2199 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2200 resource_ids_to_transfer.push_back(parent_resource);
2201 TransferableResourceArray list;
2202 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
2204 // Receive back a lost resource from the grandparent.
2205 EXPECT_EQ(1u, list.size());
2206 EXPECT_EQ(parent_resource, list[0].id);
2207 ReturnedResourceArray returned;
2208 TransferableResource::ReturnResources(list, &returned);
2209 EXPECT_EQ(1u, returned.size());
2210 EXPECT_EQ(parent_resource, returned[0].id);
2211 returned[0].lost = true;
2212 resource_provider_->ReceiveReturnsFromParent(returned);
2214 // The resource should be lost.
2215 EXPECT_TRUE(resource_provider_->IsLost(parent_resource));
2217 // Lost resources stay in use in the parent forever.
2218 EXPECT_TRUE(resource_provider_->InUseByConsumer(parent_resource));
2222 EXPECT_EQ(0u, returned_to_child.size());
2224 // Transfer resources back from the parent to the child. Set no resources as
2225 // being in use.
2226 ResourceProvider::ResourceIdSet no_resources;
2227 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
2229 // Expect the resource to be lost.
2230 ASSERT_EQ(1u, returned_to_child.size());
2231 EXPECT_TRUE(returned_to_child[0].lost);
2232 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
2233 returned_to_child.clear();
2236 // The resource should be lost.
2237 EXPECT_TRUE(child_resource_provider_->IsLost(resource));
2239 // Lost resources stay in use in the parent forever.
2240 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(resource));
2243 TEST_P(ResourceProviderTest, LostMailboxInParent) {
2244 uint32 release_sync_point = 0;
2245 bool lost_resource = false;
2246 bool release_called = false;
2247 uint32 sync_point = 0;
2248 ResourceProvider::ResourceId resource = CreateChildMailbox(
2249 &release_sync_point, &lost_resource, &release_called, &sync_point);
2251 ReturnedResourceArray returned_to_child;
2252 int child_id =
2253 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
2255 // Transfer the resource to the parent.
2256 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2257 resource_ids_to_transfer.push_back(resource);
2258 TransferableResourceArray list;
2259 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
2260 &list);
2261 EXPECT_EQ(1u, list.size());
2263 resource_provider_->ReceiveFromChild(child_id, list);
2264 ResourceProvider::ResourceIdSet resource_ids_to_receive;
2265 resource_ids_to_receive.insert(resource);
2266 resource_provider_->DeclareUsedResourcesFromChild(child_id,
2267 resource_ids_to_receive);
2270 // Lose the output surface in the parent.
2271 resource_provider_->DidLoseOutputSurface();
2274 EXPECT_EQ(0u, returned_to_child.size());
2276 // Transfer resources back from the parent to the child. Set no resources as
2277 // being in use.
2278 ResourceProvider::ResourceIdSet no_resources;
2279 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
2281 ASSERT_EQ(1u, returned_to_child.size());
2282 // Losing an output surface only loses hardware resources.
2283 EXPECT_EQ(returned_to_child[0].lost,
2284 GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE);
2285 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
2286 returned_to_child.clear();
2289 // Delete the resource in the child. Expect the resource to be lost if it's
2290 // a GL texture.
2291 child_resource_provider_->DeleteResource(resource);
2292 EXPECT_EQ(lost_resource,
2293 GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE);
2296 TEST_P(ResourceProviderTest, LostMailboxInGrandParent) {
2297 uint32 release_sync_point = 0;
2298 bool lost_resource = false;
2299 bool release_called = false;
2300 uint32 sync_point = 0;
2301 ResourceProvider::ResourceId resource = CreateChildMailbox(
2302 &release_sync_point, &lost_resource, &release_called, &sync_point);
2304 ReturnedResourceArray returned_to_child;
2305 int child_id =
2306 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
2308 // Transfer the resource to the parent.
2309 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2310 resource_ids_to_transfer.push_back(resource);
2311 TransferableResourceArray list;
2312 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
2313 &list);
2314 EXPECT_EQ(1u, list.size());
2316 resource_provider_->ReceiveFromChild(child_id, list);
2317 ResourceProvider::ResourceIdSet resource_ids_to_receive;
2318 resource_ids_to_receive.insert(resource);
2319 resource_provider_->DeclareUsedResourcesFromChild(child_id,
2320 resource_ids_to_receive);
2324 ResourceProvider::ResourceIdMap resource_map =
2325 resource_provider_->GetChildToParentMap(child_id);
2326 ResourceProvider::ResourceId parent_resource = resource_map[resource];
2327 EXPECT_NE(0u, parent_resource);
2329 // Transfer to a grandparent.
2330 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2331 resource_ids_to_transfer.push_back(parent_resource);
2332 TransferableResourceArray list;
2333 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
2335 // Receive back a lost resource from the grandparent.
2336 EXPECT_EQ(1u, list.size());
2337 EXPECT_EQ(parent_resource, list[0].id);
2338 ReturnedResourceArray returned;
2339 TransferableResource::ReturnResources(list, &returned);
2340 EXPECT_EQ(1u, returned.size());
2341 EXPECT_EQ(parent_resource, returned[0].id);
2342 returned[0].lost = true;
2343 resource_provider_->ReceiveReturnsFromParent(returned);
2347 EXPECT_EQ(0u, returned_to_child.size());
2349 // Transfer resources back from the parent to the child. Set no resources as
2350 // being in use.
2351 ResourceProvider::ResourceIdSet no_resources;
2352 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
2354 // Expect the resource to be lost.
2355 ASSERT_EQ(1u, returned_to_child.size());
2356 EXPECT_TRUE(returned_to_child[0].lost);
2357 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
2358 returned_to_child.clear();
2361 // Delete the resource in the child. Expect the resource to be lost.
2362 child_resource_provider_->DeleteResource(resource);
2363 EXPECT_TRUE(lost_resource);
2366 TEST_P(ResourceProviderTest, Shutdown) {
2367 uint32 release_sync_point = 0;
2368 bool lost_resource = false;
2369 bool release_called = false;
2370 uint32 sync_point = 0;
2371 CreateChildMailbox(
2372 &release_sync_point, &lost_resource, &release_called, &sync_point);
2374 EXPECT_EQ(0u, release_sync_point);
2375 EXPECT_FALSE(lost_resource);
2377 child_resource_provider_ = nullptr;
2379 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) {
2380 EXPECT_LE(sync_point, release_sync_point);
2382 EXPECT_TRUE(release_called);
2383 EXPECT_FALSE(lost_resource);
2386 TEST_P(ResourceProviderTest, ShutdownWithExportedResource) {
2387 uint32 release_sync_point = 0;
2388 bool lost_resource = false;
2389 bool release_called = false;
2390 uint32 sync_point = 0;
2391 ResourceProvider::ResourceId resource = CreateChildMailbox(
2392 &release_sync_point, &lost_resource, &release_called, &sync_point);
2394 // Transfer the resource, so we can't release it properly on shutdown.
2395 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2396 resource_ids_to_transfer.push_back(resource);
2397 TransferableResourceArray list;
2398 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
2399 &list);
2401 EXPECT_EQ(0u, release_sync_point);
2402 EXPECT_FALSE(lost_resource);
2404 child_resource_provider_ = nullptr;
2406 // Since the resource is in the parent, the child considers it lost.
2407 EXPECT_EQ(0u, release_sync_point);
2408 EXPECT_TRUE(lost_resource);
2411 TEST_P(ResourceProviderTest, LostContext) {
2412 // TextureMailbox callbacks only exist for GL textures for now.
2413 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
2414 return;
2415 unsigned texture = context()->createTexture();
2416 context()->bindTexture(GL_TEXTURE_2D, texture);
2417 gpu::Mailbox mailbox;
2418 context()->genMailboxCHROMIUM(mailbox.name);
2419 context()->produceTextureDirectCHROMIUM(texture, GL_TEXTURE_2D, mailbox.name);
2420 uint32 sync_point = context()->insertSyncPoint();
2422 EXPECT_LT(0u, sync_point);
2424 uint32 release_sync_point = 0;
2425 bool lost_resource = false;
2426 BlockingTaskRunner* main_thread_task_runner = NULL;
2427 scoped_ptr<SingleReleaseCallbackImpl> callback =
2428 SingleReleaseCallbackImpl::Create(base::Bind(ReleaseCallback,
2429 &release_sync_point,
2430 &lost_resource,
2431 &main_thread_task_runner));
2432 resource_provider_->CreateResourceFromTextureMailbox(
2433 TextureMailbox(mailbox, GL_TEXTURE_2D, sync_point), callback.Pass());
2435 EXPECT_EQ(0u, release_sync_point);
2436 EXPECT_FALSE(lost_resource);
2437 EXPECT_EQ(NULL, main_thread_task_runner);
2439 resource_provider_->DidLoseOutputSurface();
2440 resource_provider_ = nullptr;
2442 EXPECT_LE(sync_point, release_sync_point);
2443 EXPECT_TRUE(lost_resource);
2444 EXPECT_EQ(main_thread_task_runner_.get(), main_thread_task_runner);
2447 TEST_P(ResourceProviderTest, ScopedSampler) {
2448 // Sampling is only supported for GL textures.
2449 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
2450 return;
2452 scoped_ptr<TextureStateTrackingContext> context_owned(
2453 new TextureStateTrackingContext);
2454 TextureStateTrackingContext* context = context_owned.get();
2456 FakeOutputSurfaceClient output_surface_client;
2457 scoped_ptr<OutputSurface> output_surface(
2458 FakeOutputSurface::Create3d(context_owned.Pass()));
2459 CHECK(output_surface->BindToClient(&output_surface_client));
2461 scoped_ptr<ResourceProvider> resource_provider(
2462 ResourceProvider::Create(output_surface.get(),
2463 shared_bitmap_manager_.get(),
2464 gpu_memory_buffer_manager_.get(),
2465 NULL,
2467 false,
2468 1));
2470 gfx::Size size(1, 1);
2471 ResourceFormat format = RGBA_8888;
2472 int texture_id = 1;
2474 ResourceProvider::ResourceId id = resource_provider->CreateResource(
2475 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
2477 // Check that the texture gets created with the right sampler settings.
2478 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id))
2479 .Times(2); // Once to create and once to allocate.
2480 EXPECT_CALL(*context,
2481 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
2482 EXPECT_CALL(*context,
2483 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
2484 EXPECT_CALL(
2485 *context,
2486 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
2487 EXPECT_CALL(
2488 *context,
2489 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
2490 EXPECT_CALL(*context,
2491 texParameteri(GL_TEXTURE_2D,
2492 GL_TEXTURE_POOL_CHROMIUM,
2493 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM));
2495 resource_provider->AllocateForTesting(id);
2496 Mock::VerifyAndClearExpectations(context);
2498 // Creating a sampler with the default filter should not change any texture
2499 // parameters.
2501 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
2502 ResourceProvider::ScopedSamplerGL sampler(
2503 resource_provider.get(), id, GL_TEXTURE_2D, GL_LINEAR);
2504 Mock::VerifyAndClearExpectations(context);
2507 // Using a different filter should be reflected in the texture parameters.
2509 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
2510 EXPECT_CALL(
2511 *context,
2512 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
2513 EXPECT_CALL(
2514 *context,
2515 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
2516 ResourceProvider::ScopedSamplerGL sampler(
2517 resource_provider.get(), id, GL_TEXTURE_2D, GL_NEAREST);
2518 Mock::VerifyAndClearExpectations(context);
2521 // Test resetting to the default filter.
2523 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
2524 EXPECT_CALL(*context,
2525 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
2526 EXPECT_CALL(*context,
2527 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
2528 ResourceProvider::ScopedSamplerGL sampler(
2529 resource_provider.get(), id, GL_TEXTURE_2D, GL_LINEAR);
2530 Mock::VerifyAndClearExpectations(context);
2534 TEST_P(ResourceProviderTest, ManagedResource) {
2535 // Sampling is only supported for GL textures.
2536 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
2537 return;
2539 scoped_ptr<TextureStateTrackingContext> context_owned(
2540 new TextureStateTrackingContext);
2541 TextureStateTrackingContext* context = context_owned.get();
2543 FakeOutputSurfaceClient output_surface_client;
2544 scoped_ptr<OutputSurface> output_surface(
2545 FakeOutputSurface::Create3d(context_owned.Pass()));
2546 CHECK(output_surface->BindToClient(&output_surface_client));
2548 scoped_ptr<ResourceProvider> resource_provider(
2549 ResourceProvider::Create(output_surface.get(),
2550 shared_bitmap_manager_.get(),
2551 gpu_memory_buffer_manager_.get(),
2552 NULL,
2554 false,
2555 1));
2557 gfx::Size size(1, 1);
2558 ResourceFormat format = RGBA_8888;
2559 int texture_id = 1;
2561 // Check that the texture gets created with the right sampler settings.
2562 ResourceProvider::ResourceId id = resource_provider->CreateManagedResource(
2563 size, GL_TEXTURE_2D, GL_CLAMP_TO_EDGE,
2564 ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
2565 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
2566 EXPECT_CALL(*context,
2567 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
2568 EXPECT_CALL(*context,
2569 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
2570 EXPECT_CALL(
2571 *context,
2572 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
2573 EXPECT_CALL(
2574 *context,
2575 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
2576 EXPECT_CALL(*context,
2577 texParameteri(GL_TEXTURE_2D,
2578 GL_TEXTURE_POOL_CHROMIUM,
2579 GL_TEXTURE_POOL_MANAGED_CHROMIUM));
2580 resource_provider->CreateForTesting(id);
2581 EXPECT_NE(0u, id);
2583 Mock::VerifyAndClearExpectations(context);
2586 TEST_P(ResourceProviderTest, TextureWrapMode) {
2587 // Sampling is only supported for GL textures.
2588 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
2589 return;
2591 scoped_ptr<TextureStateTrackingContext> context_owned(
2592 new TextureStateTrackingContext);
2593 TextureStateTrackingContext* context = context_owned.get();
2595 FakeOutputSurfaceClient output_surface_client;
2596 scoped_ptr<OutputSurface> output_surface(
2597 FakeOutputSurface::Create3d(context_owned.Pass()));
2598 CHECK(output_surface->BindToClient(&output_surface_client));
2600 scoped_ptr<ResourceProvider> resource_provider(
2601 ResourceProvider::Create(output_surface.get(),
2602 shared_bitmap_manager_.get(),
2603 gpu_memory_buffer_manager_.get(),
2604 NULL,
2606 false,
2607 1));
2609 gfx::Size size(1, 1);
2610 ResourceFormat format = RGBA_8888;
2611 GLenum texture_pool = GL_TEXTURE_POOL_UNMANAGED_CHROMIUM;
2613 for (int texture_id = 1; texture_id <= 2; ++texture_id) {
2614 GLint wrap_mode = texture_id == 1 ? GL_CLAMP_TO_EDGE : GL_REPEAT;
2615 // Check that the texture gets created with the right sampler settings.
2616 ResourceProvider::ResourceId id = resource_provider->CreateGLTexture(
2617 size, GL_TEXTURE_2D, texture_pool, wrap_mode,
2618 ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
2619 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
2620 EXPECT_CALL(*context,
2621 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
2622 EXPECT_CALL(*context,
2623 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
2624 EXPECT_CALL(*context,
2625 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap_mode));
2626 EXPECT_CALL(*context,
2627 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap_mode));
2628 EXPECT_CALL(*context,
2629 texParameteri(GL_TEXTURE_2D,
2630 GL_TEXTURE_POOL_CHROMIUM,
2631 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM));
2632 resource_provider->CreateForTesting(id);
2633 EXPECT_NE(0u, id);
2635 Mock::VerifyAndClearExpectations(context);
2639 TEST_P(ResourceProviderTest, TextureHint) {
2640 // Sampling is only supported for GL textures.
2641 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
2642 return;
2644 scoped_ptr<TextureStateTrackingContext> context_owned(
2645 new TextureStateTrackingContext);
2646 TextureStateTrackingContext* context = context_owned.get();
2647 context->set_support_texture_storage(true);
2648 context->set_support_texture_usage(true);
2650 FakeOutputSurfaceClient output_surface_client;
2651 scoped_ptr<OutputSurface> output_surface(
2652 FakeOutputSurface::Create3d(context_owned.Pass()));
2653 CHECK(output_surface->BindToClient(&output_surface_client));
2655 scoped_ptr<ResourceProvider> resource_provider(
2656 ResourceProvider::Create(output_surface.get(),
2657 shared_bitmap_manager_.get(),
2658 gpu_memory_buffer_manager_.get(),
2659 NULL,
2661 false,
2662 1));
2664 gfx::Size size(1, 1);
2665 ResourceFormat format = RGBA_8888;
2666 GLenum texture_pool = GL_TEXTURE_POOL_UNMANAGED_CHROMIUM;
2668 const ResourceProvider::TextureHint hints[4] = {
2669 ResourceProvider::TEXTURE_HINT_DEFAULT,
2670 ResourceProvider::TEXTURE_HINT_IMMUTABLE,
2671 ResourceProvider::TEXTURE_HINT_FRAMEBUFFER,
2672 ResourceProvider::TEXTURE_HINT_IMMUTABLE_FRAMEBUFFER,
2674 for (GLuint texture_id = 1; texture_id <= arraysize(hints); ++texture_id) {
2675 // Check that the texture gets created with the right sampler settings.
2676 ResourceProvider::ResourceId id =
2677 resource_provider->CreateGLTexture(size,
2678 GL_TEXTURE_2D,
2679 texture_pool,
2680 GL_CLAMP_TO_EDGE,
2681 hints[texture_id - 1],
2682 format);
2683 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
2684 EXPECT_CALL(*context,
2685 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
2686 EXPECT_CALL(*context,
2687 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
2688 EXPECT_CALL(
2689 *context,
2690 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
2691 EXPECT_CALL(
2692 *context,
2693 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
2694 EXPECT_CALL(*context,
2695 texParameteri(GL_TEXTURE_2D,
2696 GL_TEXTURE_POOL_CHROMIUM,
2697 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM));
2698 // Check only TEXTURE_HINT_FRAMEBUFFER set GL_TEXTURE_USAGE_ANGLE.
2699 bool is_framebuffer_hint =
2700 hints[texture_id - 1] & ResourceProvider::TEXTURE_HINT_FRAMEBUFFER;
2701 EXPECT_CALL(*context,
2702 texParameteri(GL_TEXTURE_2D,
2703 GL_TEXTURE_USAGE_ANGLE,
2704 GL_FRAMEBUFFER_ATTACHMENT_ANGLE))
2705 .Times(is_framebuffer_hint ? 1 : 0);
2706 resource_provider->CreateForTesting(id);
2707 EXPECT_NE(0u, id);
2709 Mock::VerifyAndClearExpectations(context);
2713 TEST_P(ResourceProviderTest, TextureMailbox_SharedMemory) {
2714 if (GetParam() != ResourceProvider::RESOURCE_TYPE_BITMAP)
2715 return;
2717 gfx::Size size(64, 64);
2718 const uint32_t kBadBeef = 0xbadbeef;
2719 scoped_ptr<SharedBitmap> shared_bitmap(
2720 CreateAndFillSharedBitmap(shared_bitmap_manager_.get(), size, kBadBeef));
2722 FakeOutputSurfaceClient output_surface_client;
2723 scoped_ptr<OutputSurface> output_surface(
2724 FakeOutputSurface::CreateSoftware(make_scoped_ptr(
2725 new SoftwareOutputDevice)));
2726 CHECK(output_surface->BindToClient(&output_surface_client));
2728 scoped_ptr<ResourceProvider> resource_provider(
2729 ResourceProvider::Create(output_surface.get(),
2730 shared_bitmap_manager_.get(),
2731 gpu_memory_buffer_manager_.get(),
2732 main_thread_task_runner_.get(),
2734 false,
2735 1));
2737 uint32 release_sync_point = 0;
2738 bool lost_resource = false;
2739 BlockingTaskRunner* main_thread_task_runner = NULL;
2740 scoped_ptr<SingleReleaseCallbackImpl> callback =
2741 SingleReleaseCallbackImpl::Create(base::Bind(&ReleaseCallback,
2742 &release_sync_point,
2743 &lost_resource,
2744 &main_thread_task_runner));
2745 TextureMailbox mailbox(shared_bitmap.get(), size);
2747 ResourceProvider::ResourceId id =
2748 resource_provider->CreateResourceFromTextureMailbox(
2749 mailbox, callback.Pass());
2750 EXPECT_NE(0u, id);
2753 ResourceProvider::ScopedReadLockSoftware lock(resource_provider.get(), id);
2754 const SkBitmap* sk_bitmap = lock.sk_bitmap();
2755 EXPECT_EQ(sk_bitmap->width(), size.width());
2756 EXPECT_EQ(sk_bitmap->height(), size.height());
2757 EXPECT_EQ(*sk_bitmap->getAddr32(16, 16), kBadBeef);
2760 resource_provider->DeleteResource(id);
2761 EXPECT_EQ(0u, release_sync_point);
2762 EXPECT_FALSE(lost_resource);
2763 EXPECT_EQ(main_thread_task_runner_.get(), main_thread_task_runner);
2766 class ResourceProviderTestTextureMailboxGLFilters
2767 : public ResourceProviderTest {
2768 public:
2769 static void RunTest(TestSharedBitmapManager* shared_bitmap_manager,
2770 TestGpuMemoryBufferManager* gpu_memory_buffer_manager,
2771 BlockingTaskRunner* main_thread_task_runner,
2772 bool mailbox_nearest_neighbor,
2773 GLenum sampler_filter) {
2774 scoped_ptr<TextureStateTrackingContext> context_owned(
2775 new TextureStateTrackingContext);
2776 TextureStateTrackingContext* context = context_owned.get();
2778 FakeOutputSurfaceClient output_surface_client;
2779 scoped_ptr<OutputSurface> output_surface(
2780 FakeOutputSurface::Create3d(context_owned.Pass()));
2781 CHECK(output_surface->BindToClient(&output_surface_client));
2783 scoped_ptr<ResourceProvider> resource_provider(
2784 ResourceProvider::Create(output_surface.get(),
2785 shared_bitmap_manager,
2786 gpu_memory_buffer_manager,
2787 main_thread_task_runner,
2789 false,
2790 1));
2792 unsigned texture_id = 1;
2793 uint32 sync_point = 30;
2794 unsigned target = GL_TEXTURE_2D;
2796 EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
2797 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
2798 EXPECT_CALL(*context, insertSyncPoint()).Times(0);
2799 EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _, _)).Times(0);
2800 EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(_, _)).Times(0);
2802 gpu::Mailbox gpu_mailbox;
2803 memcpy(gpu_mailbox.name, "Hello world", strlen("Hello world") + 1);
2804 uint32 release_sync_point = 0;
2805 bool lost_resource = false;
2806 BlockingTaskRunner* mailbox_task_runner = NULL;
2807 scoped_ptr<SingleReleaseCallbackImpl> callback =
2808 SingleReleaseCallbackImpl::Create(base::Bind(&ReleaseCallback,
2809 &release_sync_point,
2810 &lost_resource,
2811 &mailbox_task_runner));
2813 TextureMailbox mailbox(gpu_mailbox, target, sync_point);
2814 mailbox.set_nearest_neighbor(mailbox_nearest_neighbor);
2816 ResourceProvider::ResourceId id =
2817 resource_provider->CreateResourceFromTextureMailbox(mailbox,
2818 callback.Pass());
2819 EXPECT_NE(0u, id);
2821 Mock::VerifyAndClearExpectations(context);
2824 // Mailbox sync point WaitSyncPoint before using the texture.
2825 EXPECT_CALL(*context, waitSyncPoint(sync_point));
2826 resource_provider->WaitSyncPointIfNeeded(id);
2827 Mock::VerifyAndClearExpectations(context);
2829 EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(target, _))
2830 .WillOnce(Return(texture_id));
2831 EXPECT_CALL(*context, bindTexture(target, texture_id));
2833 EXPECT_CALL(*context, insertSyncPoint()).Times(0);
2834 EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _, _)).Times(0);
2836 // The sampler will reset these if |mailbox_nearest_neighbor| does not
2837 // match |sampler_filter|.
2838 if (mailbox_nearest_neighbor != (sampler_filter == GL_NEAREST)) {
2839 EXPECT_CALL(*context, texParameteri(
2840 GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, sampler_filter));
2841 EXPECT_CALL(*context, texParameteri(
2842 GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, sampler_filter));
2845 ResourceProvider::ScopedSamplerGL lock(
2846 resource_provider.get(), id, sampler_filter);
2847 Mock::VerifyAndClearExpectations(context);
2849 // When done with it, a sync point should be inserted, but no produce is
2850 // necessary.
2851 EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
2852 EXPECT_CALL(*context, insertSyncPoint());
2853 EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _, _)).Times(0);
2855 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
2856 EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(_, _)).Times(0);
2859 resource_provider->DeleteResource(id);
2860 EXPECT_EQ(0u, release_sync_point);
2861 EXPECT_FALSE(lost_resource);
2862 EXPECT_EQ(main_thread_task_runner, mailbox_task_runner);
2866 TEST_P(ResourceProviderTest, TextureMailbox_GLTexture2D_LinearToLinear) {
2867 // Mailboxing is only supported for GL textures.
2868 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
2869 return;
2871 ResourceProviderTestTextureMailboxGLFilters::RunTest(
2872 shared_bitmap_manager_.get(),
2873 gpu_memory_buffer_manager_.get(),
2874 main_thread_task_runner_.get(),
2875 false,
2876 GL_LINEAR);
2879 TEST_P(ResourceProviderTest, TextureMailbox_GLTexture2D_NearestToNearest) {
2880 // Mailboxing is only supported for GL textures.
2881 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
2882 return;
2884 ResourceProviderTestTextureMailboxGLFilters::RunTest(
2885 shared_bitmap_manager_.get(),
2886 gpu_memory_buffer_manager_.get(),
2887 main_thread_task_runner_.get(),
2888 true,
2889 GL_NEAREST);
2892 TEST_P(ResourceProviderTest, TextureMailbox_GLTexture2D_NearestToLinear) {
2893 // Mailboxing is only supported for GL textures.
2894 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
2895 return;
2897 ResourceProviderTestTextureMailboxGLFilters::RunTest(
2898 shared_bitmap_manager_.get(),
2899 gpu_memory_buffer_manager_.get(),
2900 main_thread_task_runner_.get(),
2901 true,
2902 GL_LINEAR);
2905 TEST_P(ResourceProviderTest, TextureMailbox_GLTexture2D_LinearToNearest) {
2906 // Mailboxing is only supported for GL textures.
2907 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
2908 return;
2910 ResourceProviderTestTextureMailboxGLFilters::RunTest(
2911 shared_bitmap_manager_.get(),
2912 gpu_memory_buffer_manager_.get(),
2913 main_thread_task_runner_.get(),
2914 false,
2915 GL_NEAREST);
2918 TEST_P(ResourceProviderTest, TextureMailbox_GLTextureExternalOES) {
2919 // Mailboxing is only supported for GL textures.
2920 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
2921 return;
2923 scoped_ptr<TextureStateTrackingContext> context_owned(
2924 new TextureStateTrackingContext);
2925 TextureStateTrackingContext* context = context_owned.get();
2927 FakeOutputSurfaceClient output_surface_client;
2928 scoped_ptr<OutputSurface> output_surface(
2929 FakeOutputSurface::Create3d(context_owned.Pass()));
2930 CHECK(output_surface->BindToClient(&output_surface_client));
2932 scoped_ptr<ResourceProvider> resource_provider(
2933 ResourceProvider::Create(output_surface.get(),
2934 shared_bitmap_manager_.get(),
2935 gpu_memory_buffer_manager_.get(),
2936 NULL,
2938 false,
2939 1));
2941 uint32 sync_point = 30;
2942 unsigned target = GL_TEXTURE_EXTERNAL_OES;
2944 EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
2945 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
2946 EXPECT_CALL(*context, insertSyncPoint()).Times(0);
2947 EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _, _)).Times(0);
2948 EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(_, _)).Times(0);
2950 gpu::Mailbox gpu_mailbox;
2951 memcpy(gpu_mailbox.name, "Hello world", strlen("Hello world") + 1);
2952 scoped_ptr<SingleReleaseCallbackImpl> callback =
2953 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback));
2955 TextureMailbox mailbox(gpu_mailbox, target, sync_point);
2957 ResourceProvider::ResourceId id =
2958 resource_provider->CreateResourceFromTextureMailbox(
2959 mailbox, callback.Pass());
2960 EXPECT_NE(0u, id);
2962 Mock::VerifyAndClearExpectations(context);
2965 // Mailbox sync point WaitSyncPoint before using the texture.
2966 EXPECT_CALL(*context, waitSyncPoint(sync_point));
2967 resource_provider->WaitSyncPointIfNeeded(id);
2968 Mock::VerifyAndClearExpectations(context);
2970 unsigned texture_id = 1;
2972 EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(target, _))
2973 .WillOnce(Return(texture_id));
2975 EXPECT_CALL(*context, insertSyncPoint()).Times(0);
2976 EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _, _)).Times(0);
2978 ResourceProvider::ScopedReadLockGL lock(resource_provider.get(), id);
2979 Mock::VerifyAndClearExpectations(context);
2981 // When done with it, a sync point should be inserted, but no produce is
2982 // necessary.
2983 EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
2984 EXPECT_CALL(*context, insertSyncPoint());
2985 EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _, _)).Times(0);
2987 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
2988 EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(_, _)).Times(0);
2992 TEST_P(ResourceProviderTest,
2993 TextureMailbox_WaitSyncPointIfNeeded_WithSyncPoint) {
2994 // Mailboxing is only supported for GL textures.
2995 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
2996 return;
2998 scoped_ptr<TextureStateTrackingContext> context_owned(
2999 new TextureStateTrackingContext);
3000 TextureStateTrackingContext* context = context_owned.get();
3002 FakeOutputSurfaceClient output_surface_client;
3003 scoped_ptr<OutputSurface> output_surface(
3004 FakeOutputSurface::Create3d(context_owned.Pass()));
3005 CHECK(output_surface->BindToClient(&output_surface_client));
3007 scoped_ptr<ResourceProvider> resource_provider(
3008 ResourceProvider::Create(output_surface.get(),
3009 shared_bitmap_manager_.get(),
3010 gpu_memory_buffer_manager_.get(),
3011 NULL,
3013 false,
3014 1));
3016 uint32 sync_point = 30;
3017 unsigned target = GL_TEXTURE_2D;
3019 EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
3020 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
3021 EXPECT_CALL(*context, insertSyncPoint()).Times(0);
3022 EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _, _)).Times(0);
3023 EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(_, _)).Times(0);
3025 gpu::Mailbox gpu_mailbox;
3026 memcpy(gpu_mailbox.name, "Hello world", strlen("Hello world") + 1);
3027 scoped_ptr<SingleReleaseCallbackImpl> callback =
3028 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback));
3030 TextureMailbox mailbox(gpu_mailbox, target, sync_point);
3032 ResourceProvider::ResourceId id =
3033 resource_provider->CreateResourceFromTextureMailbox(mailbox,
3034 callback.Pass());
3035 EXPECT_NE(0u, id);
3037 Mock::VerifyAndClearExpectations(context);
3040 // First call to WaitSyncPointIfNeeded should call waitSyncPoint.
3041 EXPECT_CALL(*context, waitSyncPoint(sync_point));
3042 resource_provider->WaitSyncPointIfNeeded(id);
3043 Mock::VerifyAndClearExpectations(context);
3045 // Subsequent calls to WaitSyncPointIfNeeded shouldn't call waitSyncPoint.
3046 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
3047 resource_provider->WaitSyncPointIfNeeded(id);
3048 Mock::VerifyAndClearExpectations(context);
3052 TEST_P(ResourceProviderTest, TextureMailbox_WaitSyncPointIfNeeded_NoSyncPoint) {
3053 // Mailboxing is only supported for GL textures.
3054 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
3055 return;
3057 scoped_ptr<TextureStateTrackingContext> context_owned(
3058 new TextureStateTrackingContext);
3059 TextureStateTrackingContext* context = context_owned.get();
3061 FakeOutputSurfaceClient output_surface_client;
3062 scoped_ptr<OutputSurface> output_surface(
3063 FakeOutputSurface::Create3d(context_owned.Pass()));
3064 CHECK(output_surface->BindToClient(&output_surface_client));
3066 scoped_ptr<ResourceProvider> resource_provider(
3067 ResourceProvider::Create(output_surface.get(),
3068 shared_bitmap_manager_.get(),
3069 gpu_memory_buffer_manager_.get(),
3070 NULL,
3072 false,
3073 1));
3075 uint32 sync_point = 0;
3076 unsigned target = GL_TEXTURE_2D;
3078 EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
3079 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
3080 EXPECT_CALL(*context, insertSyncPoint()).Times(0);
3081 EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _, _)).Times(0);
3082 EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(_, _)).Times(0);
3084 gpu::Mailbox gpu_mailbox;
3085 memcpy(gpu_mailbox.name, "Hello world", strlen("Hello world") + 1);
3086 scoped_ptr<SingleReleaseCallbackImpl> callback =
3087 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback));
3089 TextureMailbox mailbox(gpu_mailbox, target, sync_point);
3091 ResourceProvider::ResourceId id =
3092 resource_provider->CreateResourceFromTextureMailbox(mailbox,
3093 callback.Pass());
3094 EXPECT_NE(0u, id);
3096 Mock::VerifyAndClearExpectations(context);
3099 // WaitSyncPointIfNeeded with sync_point == 0 shouldn't call waitSyncPoint.
3100 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
3101 resource_provider->WaitSyncPointIfNeeded(id);
3102 Mock::VerifyAndClearExpectations(context);
3106 class AllocationTrackingContext3D : public TestWebGraphicsContext3D {
3107 public:
3108 MOCK_METHOD0(NextTextureId, GLuint());
3109 MOCK_METHOD1(RetireTextureId, void(GLuint id));
3110 MOCK_METHOD2(bindTexture, void(GLenum target, GLuint texture));
3111 MOCK_METHOD5(texStorage2DEXT,
3112 void(GLenum target,
3113 GLint levels,
3114 GLuint internalformat,
3115 GLint width,
3116 GLint height));
3117 MOCK_METHOD9(texImage2D,
3118 void(GLenum target,
3119 GLint level,
3120 GLenum internalformat,
3121 GLsizei width,
3122 GLsizei height,
3123 GLint border,
3124 GLenum format,
3125 GLenum type,
3126 const void* pixels));
3127 MOCK_METHOD9(texSubImage2D,
3128 void(GLenum target,
3129 GLint level,
3130 GLint xoffset,
3131 GLint yoffset,
3132 GLsizei width,
3133 GLsizei height,
3134 GLenum format,
3135 GLenum type,
3136 const void* pixels));
3137 MOCK_METHOD9(asyncTexImage2DCHROMIUM,
3138 void(GLenum target,
3139 GLint level,
3140 GLenum internalformat,
3141 GLsizei width,
3142 GLsizei height,
3143 GLint border,
3144 GLenum format,
3145 GLenum type,
3146 const void* pixels));
3147 MOCK_METHOD9(asyncTexSubImage2DCHROMIUM,
3148 void(GLenum target,
3149 GLint level,
3150 GLint xoffset,
3151 GLint yoffset,
3152 GLsizei width,
3153 GLsizei height,
3154 GLenum format,
3155 GLenum type,
3156 const void* pixels));
3157 MOCK_METHOD8(compressedTexImage2D,
3158 void(GLenum target,
3159 GLint level,
3160 GLenum internalformat,
3161 GLsizei width,
3162 GLsizei height,
3163 GLint border,
3164 GLsizei image_size,
3165 const void* data));
3166 MOCK_METHOD1(waitAsyncTexImage2DCHROMIUM, void(GLenum));
3167 MOCK_METHOD4(createImageCHROMIUM,
3168 GLuint(ClientBuffer, GLsizei, GLsizei, GLenum));
3169 MOCK_METHOD1(destroyImageCHROMIUM, void(GLuint));
3170 MOCK_METHOD2(bindTexImage2DCHROMIUM, void(GLenum, GLint));
3171 MOCK_METHOD2(releaseTexImage2DCHROMIUM, void(GLenum, GLint));
3173 // We're mocking bindTexture, so we override
3174 // TestWebGraphicsContext3D::texParameteri to avoid assertions related to the
3175 // currently bound texture.
3176 virtual void texParameteri(GLenum target, GLenum pname, GLint param) {}
3179 TEST_P(ResourceProviderTest, TextureAllocation) {
3180 // Only for GL textures.
3181 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
3182 return;
3183 scoped_ptr<AllocationTrackingContext3D> context_owned(
3184 new StrictMock<AllocationTrackingContext3D>);
3185 AllocationTrackingContext3D* context = context_owned.get();
3187 FakeOutputSurfaceClient output_surface_client;
3188 scoped_ptr<OutputSurface> output_surface(
3189 FakeOutputSurface::Create3d(context_owned.Pass()));
3190 CHECK(output_surface->BindToClient(&output_surface_client));
3192 scoped_ptr<ResourceProvider> resource_provider(
3193 ResourceProvider::Create(output_surface.get(),
3194 shared_bitmap_manager_.get(),
3195 gpu_memory_buffer_manager_.get(),
3196 NULL,
3198 false,
3199 1));
3201 gfx::Size size(2, 2);
3202 gfx::Vector2d offset(0, 0);
3203 ResourceFormat format = RGBA_8888;
3204 ResourceProvider::ResourceId id = 0;
3205 uint8_t pixels[16] = { 0 };
3206 int texture_id = 123;
3208 // Lazy allocation. Don't allocate when creating the resource.
3209 id = resource_provider->CreateResource(
3210 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
3212 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3213 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(1);
3214 resource_provider->CreateForTesting(id);
3216 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3217 resource_provider->DeleteResource(id);
3219 Mock::VerifyAndClearExpectations(context);
3221 // Do allocate when we set the pixels.
3222 id = resource_provider->CreateResource(
3223 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
3225 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3226 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(3);
3227 EXPECT_CALL(*context, texImage2D(_, _, _, 2, 2, _, _, _, _)).Times(1);
3228 EXPECT_CALL(*context, texSubImage2D(_, _, _, _, 2, 2, _, _, _)).Times(1);
3229 resource_provider->CopyToResource(id, pixels, size);
3231 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3232 resource_provider->DeleteResource(id);
3234 Mock::VerifyAndClearExpectations(context);
3236 // Same for async version.
3237 id = resource_provider->CreateResource(
3238 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
3239 resource_provider->AcquirePixelBuffer(id);
3241 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3242 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
3243 EXPECT_CALL(*context, asyncTexImage2DCHROMIUM(_, _, _, 2, 2, _, _, _, _))
3244 .Times(1);
3245 resource_provider->BeginSetPixels(id);
3246 ASSERT_TRUE(resource_provider->DidSetPixelsComplete(id));
3248 resource_provider->ReleasePixelBuffer(id);
3250 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3251 resource_provider->DeleteResource(id);
3253 Mock::VerifyAndClearExpectations(context);
3256 TEST_P(ResourceProviderTest, TextureAllocationHint) {
3257 // Only for GL textures.
3258 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
3259 return;
3260 scoped_ptr<AllocationTrackingContext3D> context_owned(
3261 new StrictMock<AllocationTrackingContext3D>);
3262 AllocationTrackingContext3D* context = context_owned.get();
3263 context->set_support_texture_storage(true);
3264 context->set_support_texture_usage(true);
3266 FakeOutputSurfaceClient output_surface_client;
3267 scoped_ptr<OutputSurface> output_surface(
3268 FakeOutputSurface::Create3d(context_owned.Pass()));
3269 CHECK(output_surface->BindToClient(&output_surface_client));
3271 scoped_ptr<ResourceProvider> resource_provider(
3272 ResourceProvider::Create(output_surface.get(),
3273 shared_bitmap_manager_.get(),
3274 gpu_memory_buffer_manager_.get(),
3275 NULL,
3277 false,
3278 1));
3280 gfx::Size size(2, 2);
3282 const ResourceFormat formats[2] = {RGBA_8888, BGRA_8888};
3283 const ResourceProvider::TextureHint hints[4] = {
3284 ResourceProvider::TEXTURE_HINT_DEFAULT,
3285 ResourceProvider::TEXTURE_HINT_IMMUTABLE,
3286 ResourceProvider::TEXTURE_HINT_FRAMEBUFFER,
3287 ResourceProvider::TEXTURE_HINT_IMMUTABLE_FRAMEBUFFER,
3289 for (size_t i = 0; i < arraysize(formats); ++i) {
3290 for (GLuint texture_id = 1; texture_id <= arraysize(hints); ++texture_id) {
3291 // Lazy allocation. Don't allocate when creating the resource.
3292 ResourceProvider::ResourceId id = resource_provider->CreateResource(
3293 size, GL_CLAMP_TO_EDGE, hints[texture_id - 1], formats[i]);
3295 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3296 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
3297 bool is_immutable_hint =
3298 hints[texture_id - 1] & ResourceProvider::TEXTURE_HINT_IMMUTABLE;
3299 bool support_immutable_texture =
3300 is_immutable_hint && formats[i] == RGBA_8888;
3301 EXPECT_CALL(*context, texStorage2DEXT(_, _, _, 2, 2))
3302 .Times(support_immutable_texture ? 1 : 0);
3303 EXPECT_CALL(*context, texImage2D(_, _, _, 2, 2, _, _, _, _))
3304 .Times(support_immutable_texture ? 0 : 1);
3305 resource_provider->AllocateForTesting(id);
3307 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3308 resource_provider->DeleteResource(id);
3310 Mock::VerifyAndClearExpectations(context);
3315 TEST_P(ResourceProviderTest, TextureAllocationHint_BGRA) {
3316 // Only for GL textures.
3317 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
3318 return;
3319 scoped_ptr<AllocationTrackingContext3D> context_owned(
3320 new StrictMock<AllocationTrackingContext3D>);
3321 AllocationTrackingContext3D* context = context_owned.get();
3322 context->set_support_texture_format_bgra8888(true);
3323 context->set_support_texture_storage(true);
3324 context->set_support_texture_usage(true);
3326 FakeOutputSurfaceClient output_surface_client;
3327 scoped_ptr<OutputSurface> output_surface(
3328 FakeOutputSurface::Create3d(context_owned.Pass()));
3329 CHECK(output_surface->BindToClient(&output_surface_client));
3331 scoped_ptr<ResourceProvider> resource_provider(
3332 ResourceProvider::Create(output_surface.get(),
3333 shared_bitmap_manager_.get(),
3334 gpu_memory_buffer_manager_.get(),
3335 NULL,
3337 false,
3338 1));
3340 gfx::Size size(2, 2);
3341 const ResourceFormat formats[2] = {RGBA_8888, BGRA_8888};
3343 const ResourceProvider::TextureHint hints[4] = {
3344 ResourceProvider::TEXTURE_HINT_DEFAULT,
3345 ResourceProvider::TEXTURE_HINT_IMMUTABLE,
3346 ResourceProvider::TEXTURE_HINT_FRAMEBUFFER,
3347 ResourceProvider::TEXTURE_HINT_IMMUTABLE_FRAMEBUFFER,
3349 for (size_t i = 0; i < arraysize(formats); ++i) {
3350 for (GLuint texture_id = 1; texture_id <= arraysize(hints); ++texture_id) {
3351 // Lazy allocation. Don't allocate when creating the resource.
3352 ResourceProvider::ResourceId id = resource_provider->CreateResource(
3353 size, GL_CLAMP_TO_EDGE, hints[texture_id - 1], formats[i]);
3355 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3356 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
3357 bool is_immutable_hint =
3358 hints[texture_id - 1] & ResourceProvider::TEXTURE_HINT_IMMUTABLE;
3359 EXPECT_CALL(*context, texStorage2DEXT(_, _, _, 2, 2))
3360 .Times(is_immutable_hint ? 1 : 0);
3361 EXPECT_CALL(*context, texImage2D(_, _, _, 2, 2, _, _, _, _))
3362 .Times(is_immutable_hint ? 0 : 1);
3363 resource_provider->AllocateForTesting(id);
3365 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3366 resource_provider->DeleteResource(id);
3368 Mock::VerifyAndClearExpectations(context);
3373 TEST_P(ResourceProviderTest, PixelBuffer_GLTexture) {
3374 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
3375 return;
3376 scoped_ptr<AllocationTrackingContext3D> context_owned(
3377 new StrictMock<AllocationTrackingContext3D>);
3378 AllocationTrackingContext3D* context = context_owned.get();
3380 FakeOutputSurfaceClient output_surface_client;
3381 scoped_ptr<OutputSurface> output_surface(
3382 FakeOutputSurface::Create3d(context_owned.Pass()));
3383 CHECK(output_surface->BindToClient(&output_surface_client));
3385 gfx::Size size(2, 2);
3386 ResourceFormat format = RGBA_8888;
3387 ResourceProvider::ResourceId id = 0;
3388 int texture_id = 123;
3390 scoped_ptr<ResourceProvider> resource_provider(
3391 ResourceProvider::Create(output_surface.get(),
3392 shared_bitmap_manager_.get(),
3393 gpu_memory_buffer_manager_.get(),
3394 NULL,
3396 false,
3397 1));
3399 id = resource_provider->CreateResource(
3400 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
3401 resource_provider->AcquirePixelBuffer(id);
3403 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3404 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
3405 EXPECT_CALL(*context, asyncTexImage2DCHROMIUM(_, _, _, 2, 2, _, _, _, _))
3406 .Times(1);
3407 resource_provider->BeginSetPixels(id);
3409 EXPECT_TRUE(resource_provider->DidSetPixelsComplete(id));
3411 resource_provider->ReleasePixelBuffer(id);
3413 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3414 resource_provider->DeleteResource(id);
3416 Mock::VerifyAndClearExpectations(context);
3419 TEST_P(ResourceProviderTest, ForcingAsyncUploadToComplete) {
3420 // Only for GL textures.
3421 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
3422 return;
3423 scoped_ptr<AllocationTrackingContext3D> context_owned(
3424 new StrictMock<AllocationTrackingContext3D>);
3425 AllocationTrackingContext3D* context = context_owned.get();
3427 FakeOutputSurfaceClient output_surface_client;
3428 scoped_ptr<OutputSurface> output_surface(
3429 FakeOutputSurface::Create3d(context_owned.Pass()));
3430 CHECK(output_surface->BindToClient(&output_surface_client));
3432 gfx::Size size(2, 2);
3433 ResourceFormat format = RGBA_8888;
3434 ResourceProvider::ResourceId id = 0;
3435 int texture_id = 123;
3437 scoped_ptr<ResourceProvider> resource_provider(
3438 ResourceProvider::Create(output_surface.get(),
3439 shared_bitmap_manager_.get(),
3440 gpu_memory_buffer_manager_.get(),
3441 NULL,
3443 false,
3444 1));
3446 id = resource_provider->CreateResource(
3447 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
3448 resource_provider->AcquirePixelBuffer(id);
3450 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3451 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
3452 EXPECT_CALL(*context, asyncTexImage2DCHROMIUM(_, _, _, 2, 2, _, _, _, _))
3453 .Times(1);
3454 resource_provider->BeginSetPixels(id);
3456 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(1);
3457 EXPECT_CALL(*context, waitAsyncTexImage2DCHROMIUM(GL_TEXTURE_2D)).Times(1);
3458 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, 0)).Times(1);
3459 resource_provider->ForceSetPixelsToComplete(id);
3461 resource_provider->ReleasePixelBuffer(id);
3463 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3464 resource_provider->DeleteResource(id);
3466 Mock::VerifyAndClearExpectations(context);
3469 TEST_P(ResourceProviderTest, PixelBufferLostContext) {
3470 scoped_ptr<AllocationTrackingContext3D> context_owned(
3471 new NiceMock<AllocationTrackingContext3D>);
3472 AllocationTrackingContext3D* context = context_owned.get();
3474 FakeOutputSurfaceClient output_surface_client;
3475 scoped_ptr<OutputSurface> output_surface(
3476 FakeOutputSurface::Create3d(context_owned.Pass()));
3477 CHECK(output_surface->BindToClient(&output_surface_client));
3479 gfx::Size size(2, 2);
3480 ResourceFormat format = RGBA_8888;
3481 ResourceProvider::ResourceId id = 0;
3482 int texture_id = 123;
3484 scoped_ptr<ResourceProvider> resource_provider(
3485 ResourceProvider::Create(output_surface.get(),
3486 shared_bitmap_manager_.get(),
3487 gpu_memory_buffer_manager_.get(),
3488 NULL,
3490 false,
3491 1));
3493 EXPECT_CALL(*context, NextTextureId()).WillRepeatedly(Return(texture_id));
3495 id = resource_provider->CreateResource(
3496 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
3497 context->loseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB,
3498 GL_INNOCENT_CONTEXT_RESET_ARB);
3500 resource_provider->AcquirePixelBuffer(id);
3501 int stride;
3502 void* buffer = resource_provider->MapPixelBuffer(id, &stride);
3503 EXPECT_FALSE(buffer);
3504 resource_provider->UnmapPixelBuffer(id);
3505 Mock::VerifyAndClearExpectations(context);
3508 TEST_P(ResourceProviderTest, Image_GLTexture) {
3509 // Only for GL textures.
3510 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
3511 return;
3512 scoped_ptr<AllocationTrackingContext3D> context_owned(
3513 new StrictMock<AllocationTrackingContext3D>);
3514 AllocationTrackingContext3D* context = context_owned.get();
3516 FakeOutputSurfaceClient output_surface_client;
3517 scoped_ptr<OutputSurface> output_surface(
3518 FakeOutputSurface::Create3d(context_owned.Pass()));
3519 CHECK(output_surface->BindToClient(&output_surface_client));
3521 const int kWidth = 2;
3522 const int kHeight = 2;
3523 gfx::Size size(kWidth, kHeight);
3524 ResourceFormat format = RGBA_8888;
3525 ResourceProvider::ResourceId id = 0;
3526 const unsigned kTextureId = 123u;
3527 const unsigned kImageId = 234u;
3529 scoped_ptr<ResourceProvider> resource_provider(
3530 ResourceProvider::Create(output_surface.get(),
3531 shared_bitmap_manager_.get(),
3532 gpu_memory_buffer_manager_.get(),
3533 NULL,
3535 false,
3536 1));
3538 id = resource_provider->CreateResource(
3539 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
3541 EXPECT_CALL(*context, createImageCHROMIUM(_, kWidth, kHeight, GL_RGBA))
3542 .WillOnce(Return(kImageId))
3543 .RetiresOnSaturation();
3545 ResourceProvider::ScopedWriteLockGpuMemoryBuffer lock(
3546 resource_provider.get(), id);
3547 EXPECT_TRUE(!!lock.GetGpuMemoryBuffer());
3550 EXPECT_CALL(*context, NextTextureId())
3551 .WillOnce(Return(kTextureId))
3552 .RetiresOnSaturation();
3553 // Once in CreateTextureId and once in BindForSampling
3554 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kTextureId)).Times(2)
3555 .RetiresOnSaturation();
3556 EXPECT_CALL(*context, bindTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId))
3557 .Times(1)
3558 .RetiresOnSaturation();
3560 ResourceProvider::ScopedSamplerGL lock_gl(
3561 resource_provider.get(), id, GL_TEXTURE_2D, GL_LINEAR);
3562 EXPECT_EQ(kTextureId, lock_gl.texture_id());
3566 ResourceProvider::ScopedWriteLockGpuMemoryBuffer lock(
3567 resource_provider.get(), id);
3568 EXPECT_TRUE(!!lock.GetGpuMemoryBuffer());
3571 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kTextureId)).Times(1)
3572 .RetiresOnSaturation();
3573 EXPECT_CALL(*context, releaseTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId))
3574 .Times(1)
3575 .RetiresOnSaturation();
3576 EXPECT_CALL(*context, bindTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId))
3577 .Times(1)
3578 .RetiresOnSaturation();
3579 EXPECT_CALL(*context, RetireTextureId(kTextureId))
3580 .Times(1)
3581 .RetiresOnSaturation();
3583 ResourceProvider::ScopedSamplerGL lock_gl(
3584 resource_provider.get(), id, GL_TEXTURE_2D, GL_LINEAR);
3585 EXPECT_EQ(kTextureId, lock_gl.texture_id());
3588 EXPECT_CALL(*context, destroyImageCHROMIUM(kImageId))
3589 .Times(1)
3590 .RetiresOnSaturation();
3593 TEST_P(ResourceProviderTest, CopyResource_GLTexture) {
3594 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
3595 return;
3596 scoped_ptr<AllocationTrackingContext3D> context_owned(
3597 new StrictMock<AllocationTrackingContext3D>);
3598 AllocationTrackingContext3D* context = context_owned.get();
3599 context_owned->set_support_sync_query(true);
3601 FakeOutputSurfaceClient output_surface_client;
3602 scoped_ptr<OutputSurface> output_surface(
3603 FakeOutputSurface::Create3d(context_owned.Pass()));
3604 ASSERT_TRUE(output_surface->BindToClient(&output_surface_client));
3606 const int kWidth = 2;
3607 const int kHeight = 2;
3608 gfx::Size size(kWidth, kHeight);
3609 ResourceFormat format = RGBA_8888;
3610 ResourceProvider::ResourceId source_id = 0;
3611 ResourceProvider::ResourceId dest_id = 0;
3612 const unsigned kSourceTextureId = 123u;
3613 const unsigned kDestTextureId = 321u;
3614 const unsigned kImageId = 234u;
3616 scoped_ptr<ResourceProvider> resource_provider(
3617 ResourceProvider::Create(output_surface.get(),
3618 shared_bitmap_manager_.get(),
3619 gpu_memory_buffer_manager_.get(),
3620 NULL,
3622 false,
3623 1));
3625 source_id = resource_provider->CreateResource(
3626 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
3628 EXPECT_CALL(*context, createImageCHROMIUM(_, kWidth, kHeight, GL_RGBA))
3629 .WillOnce(Return(kImageId))
3630 .RetiresOnSaturation();
3632 ResourceProvider::ScopedWriteLockGpuMemoryBuffer lock(
3633 resource_provider.get(), source_id);
3634 EXPECT_TRUE(!!lock.GetGpuMemoryBuffer());
3636 Mock::VerifyAndClearExpectations(context);
3638 dest_id = resource_provider->CreateResource(
3639 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
3641 EXPECT_CALL(*context, NextTextureId())
3642 .WillOnce(Return(kDestTextureId))
3643 .RetiresOnSaturation();
3644 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kDestTextureId))
3645 .Times(2)
3646 .RetiresOnSaturation();
3647 EXPECT_CALL(*context, texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA,
3648 GL_UNSIGNED_BYTE, nullptr))
3649 .Times(1)
3650 .RetiresOnSaturation();
3651 EXPECT_CALL(*context, NextTextureId())
3652 .WillOnce(Return(kSourceTextureId))
3653 .RetiresOnSaturation();
3654 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kSourceTextureId))
3655 .Times(2)
3656 .RetiresOnSaturation();
3657 EXPECT_CALL(*context, bindTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId))
3658 .Times(1)
3659 .RetiresOnSaturation();
3660 resource_provider->CopyResource(source_id, dest_id);
3661 Mock::VerifyAndClearExpectations(context);
3663 EXPECT_CALL(*context, destroyImageCHROMIUM(kImageId))
3664 .Times(1)
3665 .RetiresOnSaturation();
3666 EXPECT_CALL(*context, RetireTextureId(kSourceTextureId))
3667 .Times(1)
3668 .RetiresOnSaturation();
3669 EXPECT_CALL(*context, RetireTextureId(kDestTextureId))
3670 .Times(1)
3671 .RetiresOnSaturation();
3672 resource_provider->DeleteResource(source_id);
3673 resource_provider->DeleteResource(dest_id);
3676 TEST_P(ResourceProviderTest, CompressedTextureETC1Allocate) {
3677 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
3678 return;
3680 scoped_ptr<AllocationTrackingContext3D> context_owned(
3681 new AllocationTrackingContext3D);
3682 AllocationTrackingContext3D* context = context_owned.get();
3683 context_owned->set_support_compressed_texture_etc1(true);
3685 FakeOutputSurfaceClient output_surface_client;
3686 scoped_ptr<OutputSurface> output_surface(
3687 FakeOutputSurface::Create3d(context_owned.Pass()));
3688 CHECK(output_surface->BindToClient(&output_surface_client));
3690 gfx::Size size(4, 4);
3691 scoped_ptr<ResourceProvider> resource_provider(
3692 ResourceProvider::Create(output_surface.get(),
3693 shared_bitmap_manager_.get(),
3694 gpu_memory_buffer_manager_.get(),
3695 NULL,
3697 false,
3698 1));
3699 int texture_id = 123;
3701 ResourceProvider::ResourceId id = resource_provider->CreateResource(
3702 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, ETC1);
3703 EXPECT_NE(0u, id);
3704 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3705 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
3706 resource_provider->AllocateForTesting(id);
3708 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3709 resource_provider->DeleteResource(id);
3712 TEST_P(ResourceProviderTest, CompressedTextureETC1Upload) {
3713 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
3714 return;
3716 scoped_ptr<AllocationTrackingContext3D> context_owned(
3717 new AllocationTrackingContext3D);
3718 AllocationTrackingContext3D* context = context_owned.get();
3719 context_owned->set_support_compressed_texture_etc1(true);
3721 FakeOutputSurfaceClient output_surface_client;
3722 scoped_ptr<OutputSurface> output_surface(
3723 FakeOutputSurface::Create3d(context_owned.Pass()));
3724 CHECK(output_surface->BindToClient(&output_surface_client));
3726 gfx::Size size(4, 4);
3727 scoped_ptr<ResourceProvider> resource_provider(
3728 ResourceProvider::Create(output_surface.get(),
3729 shared_bitmap_manager_.get(),
3730 gpu_memory_buffer_manager_.get(),
3731 NULL,
3733 false,
3734 1));
3735 int texture_id = 123;
3736 uint8_t pixels[8];
3738 ResourceProvider::ResourceId id = resource_provider->CreateResource(
3739 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, ETC1);
3740 EXPECT_NE(0u, id);
3741 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3742 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(3);
3743 EXPECT_CALL(*context,
3744 compressedTexImage2D(
3745 _, 0, _, size.width(), size.height(), _, _, _)).Times(1);
3746 resource_provider->CopyToResource(id, pixels, size);
3748 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3749 resource_provider->DeleteResource(id);
3752 INSTANTIATE_TEST_CASE_P(
3753 ResourceProviderTests,
3754 ResourceProviderTest,
3755 ::testing::Values(ResourceProvider::RESOURCE_TYPE_GL_TEXTURE,
3756 ResourceProvider::RESOURCE_TYPE_BITMAP));
3758 class TextureIdAllocationTrackingContext : public TestWebGraphicsContext3D {
3759 public:
3760 GLuint NextTextureId() override {
3761 base::AutoLock lock(namespace_->lock);
3762 return namespace_->next_texture_id++;
3764 void RetireTextureId(GLuint) override {}
3765 GLuint PeekTextureId() {
3766 base::AutoLock lock(namespace_->lock);
3767 return namespace_->next_texture_id;
3771 TEST(ResourceProviderTest, TextureAllocationChunkSize) {
3772 scoped_ptr<TextureIdAllocationTrackingContext> context_owned(
3773 new TextureIdAllocationTrackingContext);
3774 TextureIdAllocationTrackingContext* context = context_owned.get();
3776 FakeOutputSurfaceClient output_surface_client;
3777 scoped_ptr<OutputSurface> output_surface(
3778 FakeOutputSurface::Create3d(context_owned.Pass()));
3779 CHECK(output_surface->BindToClient(&output_surface_client));
3780 scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
3781 new TestSharedBitmapManager());
3783 gfx::Size size(1, 1);
3784 ResourceFormat format = RGBA_8888;
3787 size_t kTextureAllocationChunkSize = 1;
3788 scoped_ptr<ResourceProvider> resource_provider(
3789 ResourceProvider::Create(output_surface.get(),
3790 shared_bitmap_manager.get(),
3791 NULL,
3792 NULL,
3794 false,
3795 kTextureAllocationChunkSize));
3797 ResourceProvider::ResourceId id = resource_provider->CreateResource(
3798 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE,
3799 format);
3800 resource_provider->AllocateForTesting(id);
3801 Mock::VerifyAndClearExpectations(context);
3803 DCHECK_EQ(2u, context->PeekTextureId());
3804 resource_provider->DeleteResource(id);
3808 size_t kTextureAllocationChunkSize = 8;
3809 scoped_ptr<ResourceProvider> resource_provider(
3810 ResourceProvider::Create(output_surface.get(),
3811 shared_bitmap_manager.get(),
3812 NULL,
3813 NULL,
3815 false,
3816 kTextureAllocationChunkSize));
3818 ResourceProvider::ResourceId id = resource_provider->CreateResource(
3819 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE,
3820 format);
3821 resource_provider->AllocateForTesting(id);
3822 Mock::VerifyAndClearExpectations(context);
3824 DCHECK_EQ(10u, context->PeekTextureId());
3825 resource_provider->DeleteResource(id);
3829 } // namespace
3830 } // namespace cc