ServiceWorker: Introduce SWMessageSender in order to mock IPC messaging
[chromium-blink-merge.git] / cc / resources / resource_provider_unittest.cc
blob24b91bf440a2453c5a8a8a081151699bf80fdfe5
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;
374 case ResourceProvider::RESOURCE_TYPE_INVALID:
375 NOTREACHED();
376 break;
380 class ResourceProviderTest
381 : public testing::TestWithParam<ResourceProvider::ResourceType> {
382 public:
383 ResourceProviderTest()
384 : shared_data_(ContextSharedData::Create()),
385 context3d_(NULL),
386 child_context_(NULL),
387 main_thread_task_runner_(BlockingTaskRunner::Create(NULL)) {
388 switch (GetParam()) {
389 case ResourceProvider::RESOURCE_TYPE_GL_TEXTURE: {
390 scoped_ptr<ResourceProviderContext> context3d(
391 ResourceProviderContext::Create(shared_data_.get()));
392 context3d_ = context3d.get();
394 scoped_refptr<TestContextProvider> context_provider =
395 TestContextProvider::Create(context3d.Pass());
397 output_surface_ = FakeOutputSurface::Create3d(context_provider);
399 scoped_ptr<ResourceProviderContext> child_context_owned =
400 ResourceProviderContext::Create(shared_data_.get());
401 child_context_ = child_context_owned.get();
402 child_output_surface_ =
403 FakeOutputSurface::Create3d(child_context_owned.Pass());
404 break;
406 case ResourceProvider::RESOURCE_TYPE_BITMAP:
407 output_surface_ = FakeOutputSurface::CreateSoftware(
408 make_scoped_ptr(new SoftwareOutputDevice));
409 child_output_surface_ = FakeOutputSurface::CreateSoftware(
410 make_scoped_ptr(new SoftwareOutputDevice));
411 break;
412 case ResourceProvider::RESOURCE_TYPE_INVALID:
413 NOTREACHED();
414 break;
416 CHECK(output_surface_->BindToClient(&output_surface_client_));
417 CHECK(child_output_surface_->BindToClient(&child_output_surface_client_));
419 shared_bitmap_manager_.reset(new TestSharedBitmapManager);
420 gpu_memory_buffer_manager_.reset(new TestGpuMemoryBufferManager);
422 resource_provider_ =
423 ResourceProvider::Create(output_surface_.get(),
424 shared_bitmap_manager_.get(),
425 gpu_memory_buffer_manager_.get(),
426 main_thread_task_runner_.get(),
428 false,
430 child_resource_provider_ =
431 ResourceProvider::Create(child_output_surface_.get(),
432 shared_bitmap_manager_.get(),
433 gpu_memory_buffer_manager_.get(),
434 main_thread_task_runner_.get(),
436 false,
440 static void CollectResources(ReturnedResourceArray* array,
441 const ReturnedResourceArray& returned,
442 BlockingTaskRunner* main_thread_task_runner) {
443 array->insert(array->end(), returned.begin(), returned.end());
446 static ReturnCallback GetReturnCallback(ReturnedResourceArray* array) {
447 return base::Bind(&ResourceProviderTest::CollectResources, array);
450 static void SetResourceFilter(ResourceProvider* resource_provider,
451 ResourceProvider::ResourceId id,
452 GLenum filter) {
453 ResourceProvider::ScopedSamplerGL sampler(
454 resource_provider, id, GL_TEXTURE_2D, filter);
457 ResourceProviderContext* context() { return context3d_; }
459 ResourceProvider::ResourceId CreateChildMailbox(uint32* release_sync_point,
460 bool* lost_resource,
461 bool* release_called,
462 uint32* sync_point) {
463 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) {
464 unsigned texture = child_context_->createTexture();
465 gpu::Mailbox gpu_mailbox;
466 child_context_->genMailboxCHROMIUM(gpu_mailbox.name);
467 child_context_->produceTextureDirectCHROMIUM(texture, GL_TEXTURE_2D,
468 gpu_mailbox.name);
469 *sync_point = child_context_->insertSyncPoint();
470 EXPECT_LT(0u, *sync_point);
472 scoped_ptr<SharedBitmap> shared_bitmap;
473 scoped_ptr<SingleReleaseCallbackImpl> callback =
474 SingleReleaseCallbackImpl::Create(base::Bind(
475 ReleaseSharedBitmapCallback, base::Passed(&shared_bitmap),
476 release_called, release_sync_point, lost_resource));
477 return child_resource_provider_->CreateResourceFromTextureMailbox(
478 TextureMailbox(gpu_mailbox, GL_TEXTURE_2D, *sync_point),
479 callback.Pass());
480 } else {
481 gfx::Size size(64, 64);
482 scoped_ptr<SharedBitmap> shared_bitmap(
483 CreateAndFillSharedBitmap(shared_bitmap_manager_.get(), size, 0));
485 SharedBitmap* shared_bitmap_ptr = shared_bitmap.get();
486 scoped_ptr<SingleReleaseCallbackImpl> callback =
487 SingleReleaseCallbackImpl::Create(base::Bind(
488 ReleaseSharedBitmapCallback, base::Passed(&shared_bitmap),
489 release_called, release_sync_point, lost_resource));
490 return child_resource_provider_->CreateResourceFromTextureMailbox(
491 TextureMailbox(shared_bitmap_ptr, size), callback.Pass());
495 protected:
496 scoped_ptr<ContextSharedData> shared_data_;
497 ResourceProviderContext* context3d_;
498 ResourceProviderContext* child_context_;
499 FakeOutputSurfaceClient output_surface_client_;
500 FakeOutputSurfaceClient child_output_surface_client_;
501 scoped_ptr<OutputSurface> output_surface_;
502 scoped_ptr<OutputSurface> child_output_surface_;
503 scoped_ptr<BlockingTaskRunner> main_thread_task_runner_;
504 scoped_ptr<ResourceProvider> resource_provider_;
505 scoped_ptr<ResourceProvider> child_resource_provider_;
506 scoped_ptr<TestSharedBitmapManager> shared_bitmap_manager_;
507 scoped_ptr<TestGpuMemoryBufferManager> gpu_memory_buffer_manager_;
510 void CheckCreateResource(ResourceProvider::ResourceType expected_default_type,
511 ResourceProvider* resource_provider,
512 ResourceProviderContext* context) {
513 DCHECK_EQ(expected_default_type, resource_provider->default_resource_type());
515 gfx::Size size(1, 1);
516 ResourceFormat format = RGBA_8888;
517 size_t pixel_size = TextureSizeBytes(size, format);
518 ASSERT_EQ(4U, pixel_size);
520 ResourceProvider::ResourceId id = resource_provider->CreateResource(
521 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
522 EXPECT_EQ(1, static_cast<int>(resource_provider->num_resources()));
523 if (expected_default_type == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
524 EXPECT_EQ(0u, context->NumTextures());
526 uint8_t data[4] = { 1, 2, 3, 4 };
527 resource_provider->CopyToResource(id, data, size);
528 if (expected_default_type == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
529 EXPECT_EQ(1u, context->NumTextures());
531 uint8_t result[4] = { 0 };
532 GetResourcePixels(resource_provider, context, id, size, format, result);
533 EXPECT_EQ(0, memcmp(data, result, pixel_size));
535 resource_provider->DeleteResource(id);
536 EXPECT_EQ(0, static_cast<int>(resource_provider->num_resources()));
537 if (expected_default_type == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
538 EXPECT_EQ(0u, context->NumTextures());
541 TEST_P(ResourceProviderTest, Basic) {
542 CheckCreateResource(GetParam(), resource_provider_.get(), context());
545 TEST_P(ResourceProviderTest, Upload) {
546 gfx::Size size(2, 2);
547 ResourceFormat format = RGBA_8888;
548 size_t pixel_size = TextureSizeBytes(size, format);
549 ASSERT_EQ(16U, pixel_size);
551 ResourceProvider::ResourceId id = resource_provider_->CreateResource(
552 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
554 uint8_t image[16] = { 0 };
555 gfx::Rect image_rect(size);
556 resource_provider_->SetPixels(
557 id, image, image_rect, image_rect, gfx::Vector2d());
559 for (uint8_t i = 0; i < pixel_size; ++i)
560 image[i] = i;
562 uint8_t result[16] = { 0 };
564 gfx::Rect source_rect(0, 0, 1, 1);
565 gfx::Vector2d dest_offset(0, 0);
566 resource_provider_->SetPixels(
567 id, image, image_rect, source_rect, dest_offset);
569 uint8_t expected[16] = { 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
570 GetResourcePixels(
571 resource_provider_.get(), context(), id, size, format, result);
572 EXPECT_EQ(0, memcmp(expected, result, pixel_size));
575 gfx::Rect source_rect(0, 0, 1, 1);
576 gfx::Vector2d dest_offset(1, 1);
577 resource_provider_->SetPixels(
578 id, image, image_rect, source_rect, dest_offset);
580 uint8_t expected[16] = { 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3 };
581 GetResourcePixels(
582 resource_provider_.get(), context(), id, size, format, result);
583 EXPECT_EQ(0, memcmp(expected, result, pixel_size));
586 gfx::Rect source_rect(1, 0, 1, 1);
587 gfx::Vector2d dest_offset(0, 1);
588 resource_provider_->SetPixels(
589 id, image, image_rect, source_rect, dest_offset);
591 uint8_t expected[16] = { 0, 1, 2, 3, 0, 0, 0, 0, 4, 5, 6, 7, 0, 1, 2, 3 };
592 GetResourcePixels(
593 resource_provider_.get(), context(), id, size, format, result);
594 EXPECT_EQ(0, memcmp(expected, result, pixel_size));
597 gfx::Rect offset_image_rect(gfx::Point(100, 100), size);
598 gfx::Rect source_rect(100, 100, 1, 1);
599 gfx::Vector2d dest_offset(1, 0);
600 resource_provider_->SetPixels(
601 id, image, offset_image_rect, source_rect, dest_offset);
603 uint8_t expected[16] = { 0, 1, 2, 3, 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3 };
604 GetResourcePixels(
605 resource_provider_.get(), context(), id, size, format, result);
606 EXPECT_EQ(0, memcmp(expected, result, pixel_size));
609 resource_provider_->DeleteResource(id);
612 TEST_P(ResourceProviderTest, SimpleUpload) {
613 gfx::Size size(2, 2);
614 ResourceFormat format = RGBA_8888;
615 size_t pixel_size = TextureSizeBytes(size, format);
616 ASSERT_EQ(16U, pixel_size);
618 ResourceProvider::ResourceId id = resource_provider_->CreateResource(
619 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
621 uint8_t image[16] = {0};
622 resource_provider_->CopyToResource(id, image, size);
624 uint8_t result[16] = {0};
625 uint8_t expected[16] = {0};
626 GetResourcePixels(resource_provider_.get(), context(), id, size, format,
627 result);
628 EXPECT_EQ(0, memcmp(expected, result, pixel_size));
631 for (uint8_t i = 0; i < pixel_size; ++i)
632 image[i] = i;
633 resource_provider_->CopyToResource(id, image, size);
635 uint8_t result[16] = {0};
636 uint8_t expected[16] = {
637 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
638 GetResourcePixels(resource_provider_.get(), context(), id, size, format,
639 result);
640 EXPECT_EQ(0, memcmp(expected, result, pixel_size));
644 TEST_P(ResourceProviderTest, TransferGLResources) {
645 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
646 return;
647 gfx::Size size(1, 1);
648 ResourceFormat format = RGBA_8888;
649 size_t pixel_size = TextureSizeBytes(size, format);
650 ASSERT_EQ(4U, pixel_size);
652 ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource(
653 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
654 uint8_t data1[4] = { 1, 2, 3, 4 };
655 child_resource_provider_->CopyToResource(id1, data1, size);
657 ResourceProvider::ResourceId id2 = child_resource_provider_->CreateResource(
658 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
659 uint8_t data2[4] = { 5, 5, 5, 5 };
660 child_resource_provider_->CopyToResource(id2, data2, size);
662 ResourceProvider::ResourceId id3 = child_resource_provider_->CreateResource(
663 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
665 ResourceProvider::ScopedWriteLockGpuMemoryBuffer lock(
666 child_resource_provider_.get(), id3);
667 EXPECT_TRUE(!!lock.GetGpuMemoryBuffer());
670 GLuint external_texture_id = child_context_->createExternalTexture();
672 gpu::Mailbox external_mailbox;
673 child_context_->genMailboxCHROMIUM(external_mailbox.name);
674 child_context_->produceTextureDirectCHROMIUM(
675 external_texture_id, GL_TEXTURE_EXTERNAL_OES, external_mailbox.name);
676 const GLuint external_sync_point = child_context_->insertSyncPoint();
677 ResourceProvider::ResourceId id4 =
678 child_resource_provider_->CreateResourceFromTextureMailbox(
679 TextureMailbox(
680 external_mailbox, GL_TEXTURE_EXTERNAL_OES, external_sync_point),
681 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback)));
683 ReturnedResourceArray returned_to_child;
684 int child_id =
685 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
687 // Transfer some resources to the parent.
688 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
689 resource_ids_to_transfer.push_back(id1);
690 resource_ids_to_transfer.push_back(id2);
691 resource_ids_to_transfer.push_back(id3);
692 resource_ids_to_transfer.push_back(id4);
693 TransferableResourceArray list;
694 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
695 &list);
696 ASSERT_EQ(4u, list.size());
697 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
698 EXPECT_NE(0u, list[1].mailbox_holder.sync_point);
699 EXPECT_EQ(list[0].mailbox_holder.sync_point,
700 list[1].mailbox_holder.sync_point);
701 EXPECT_NE(0u, list[2].mailbox_holder.sync_point);
702 EXPECT_EQ(list[0].mailbox_holder.sync_point,
703 list[2].mailbox_holder.sync_point);
704 EXPECT_EQ(external_sync_point, list[3].mailbox_holder.sync_point);
705 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
706 list[0].mailbox_holder.texture_target);
707 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
708 list[1].mailbox_holder.texture_target);
709 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
710 list[2].mailbox_holder.texture_target);
711 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_EXTERNAL_OES),
712 list[3].mailbox_holder.texture_target);
713 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
714 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
715 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
716 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id4));
717 resource_provider_->ReceiveFromChild(child_id, list);
718 EXPECT_NE(list[0].mailbox_holder.sync_point,
719 context3d_->last_waited_sync_point());
721 resource_provider_->WaitSyncPointIfNeeded(list[0].id);
722 ResourceProvider::ScopedReadLockGL lock(resource_provider_.get(),
723 list[0].id);
725 EXPECT_EQ(list[0].mailbox_holder.sync_point,
726 context3d_->last_waited_sync_point());
727 resource_provider_->DeclareUsedResourcesFromChild(child_id,
728 resource_ids_to_transfer);
731 EXPECT_EQ(4u, resource_provider_->num_resources());
732 ResourceProvider::ResourceIdMap resource_map =
733 resource_provider_->GetChildToParentMap(child_id);
734 ResourceProvider::ResourceId mapped_id1 = resource_map[id1];
735 ResourceProvider::ResourceId mapped_id2 = resource_map[id2];
736 ResourceProvider::ResourceId mapped_id3 = resource_map[id3];
737 ResourceProvider::ResourceId mapped_id4 = resource_map[id4];
738 EXPECT_NE(0u, mapped_id1);
739 EXPECT_NE(0u, mapped_id2);
740 EXPECT_NE(0u, mapped_id3);
741 EXPECT_NE(0u, mapped_id4);
742 EXPECT_FALSE(resource_provider_->InUseByConsumer(id1));
743 EXPECT_FALSE(resource_provider_->InUseByConsumer(id2));
744 EXPECT_FALSE(resource_provider_->InUseByConsumer(id3));
745 EXPECT_FALSE(resource_provider_->InUseByConsumer(id4));
747 uint8_t result[4] = { 0 };
748 GetResourcePixels(
749 resource_provider_.get(), context(), mapped_id1, size, format, result);
750 EXPECT_EQ(0, memcmp(data1, result, pixel_size));
752 GetResourcePixels(
753 resource_provider_.get(), context(), mapped_id2, size, format, result);
754 EXPECT_EQ(0, memcmp(data2, result, pixel_size));
757 // Check that transfering again the same resource from the child to the
758 // parent works.
759 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
760 resource_ids_to_transfer.push_back(id1);
761 resource_ids_to_transfer.push_back(id2);
762 resource_ids_to_transfer.push_back(id3);
763 TransferableResourceArray list;
764 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
765 &list);
766 EXPECT_EQ(3u, list.size());
767 EXPECT_EQ(id1, list[0].id);
768 EXPECT_EQ(id2, list[1].id);
769 EXPECT_EQ(id3, list[2].id);
770 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
771 list[0].mailbox_holder.texture_target);
772 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
773 list[1].mailbox_holder.texture_target);
774 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
775 list[2].mailbox_holder.texture_target);
776 ReturnedResourceArray returned;
777 TransferableResource::ReturnResources(list, &returned);
778 child_resource_provider_->ReceiveReturnsFromParent(returned);
779 // ids were exported twice, we returned them only once, they should still
780 // be in-use.
781 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
782 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
783 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
786 EXPECT_EQ(0u, returned_to_child.size());
788 // Transfer resources back from the parent to the child. Set no resources as
789 // being in use.
790 ResourceProvider::ResourceIdArray no_resources;
791 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
793 ASSERT_EQ(4u, returned_to_child.size());
794 EXPECT_NE(0u, returned_to_child[0].sync_point);
795 EXPECT_NE(0u, returned_to_child[1].sync_point);
796 EXPECT_NE(0u, returned_to_child[2].sync_point);
797 EXPECT_NE(0u, returned_to_child[3].sync_point);
798 EXPECT_FALSE(returned_to_child[0].lost);
799 EXPECT_FALSE(returned_to_child[1].lost);
800 EXPECT_FALSE(returned_to_child[2].lost);
801 EXPECT_FALSE(returned_to_child[3].lost);
802 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
803 returned_to_child.clear();
805 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id1));
806 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id2));
807 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id3));
808 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id4));
811 child_resource_provider_->WaitSyncPointIfNeeded(id1);
812 ResourceProvider::ScopedReadLockGL lock(child_resource_provider_.get(),
813 id1);
814 ASSERT_NE(0U, lock.texture_id());
815 child_context_->bindTexture(GL_TEXTURE_2D, lock.texture_id());
816 child_context_->GetPixels(size, format, result);
817 EXPECT_EQ(0, memcmp(data1, result, pixel_size));
820 child_resource_provider_->WaitSyncPointIfNeeded(id2);
821 ResourceProvider::ScopedReadLockGL lock(child_resource_provider_.get(),
822 id2);
823 ASSERT_NE(0U, lock.texture_id());
824 child_context_->bindTexture(GL_TEXTURE_2D, lock.texture_id());
825 child_context_->GetPixels(size, format, result);
826 EXPECT_EQ(0, memcmp(data2, result, pixel_size));
829 child_resource_provider_->WaitSyncPointIfNeeded(id3);
830 ResourceProvider::ScopedReadLockGL lock(child_resource_provider_.get(),
831 id3);
832 ASSERT_NE(0U, lock.texture_id());
833 child_context_->bindTexture(GL_TEXTURE_2D, lock.texture_id());
836 // Transfer resources to the parent again.
837 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
838 resource_ids_to_transfer.push_back(id1);
839 resource_ids_to_transfer.push_back(id2);
840 resource_ids_to_transfer.push_back(id3);
841 resource_ids_to_transfer.push_back(id4);
842 TransferableResourceArray list;
843 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
844 &list);
845 ASSERT_EQ(4u, list.size());
846 EXPECT_EQ(id1, list[0].id);
847 EXPECT_EQ(id2, list[1].id);
848 EXPECT_EQ(id3, list[2].id);
849 EXPECT_EQ(id4, list[3].id);
850 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
851 EXPECT_NE(0u, list[1].mailbox_holder.sync_point);
852 EXPECT_NE(0u, list[2].mailbox_holder.sync_point);
853 EXPECT_NE(0u, list[3].mailbox_holder.sync_point);
854 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
855 list[0].mailbox_holder.texture_target);
856 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
857 list[1].mailbox_holder.texture_target);
858 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
859 list[2].mailbox_holder.texture_target);
860 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_EXTERNAL_OES),
861 list[3].mailbox_holder.texture_target);
862 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
863 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
864 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
865 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id4));
866 resource_provider_->ReceiveFromChild(child_id, list);
867 resource_provider_->DeclareUsedResourcesFromChild(child_id,
868 resource_ids_to_transfer);
871 EXPECT_EQ(0u, returned_to_child.size());
873 EXPECT_EQ(4u, resource_provider_->num_resources());
874 resource_provider_->DestroyChild(child_id);
875 EXPECT_EQ(0u, resource_provider_->num_resources());
877 ASSERT_EQ(4u, returned_to_child.size());
878 EXPECT_NE(0u, returned_to_child[0].sync_point);
879 EXPECT_NE(0u, returned_to_child[1].sync_point);
880 EXPECT_NE(0u, returned_to_child[2].sync_point);
881 EXPECT_NE(0u, returned_to_child[3].sync_point);
882 EXPECT_FALSE(returned_to_child[0].lost);
883 EXPECT_FALSE(returned_to_child[1].lost);
884 EXPECT_FALSE(returned_to_child[2].lost);
885 EXPECT_FALSE(returned_to_child[3].lost);
888 TEST_P(ResourceProviderTest, ReadLockCountStopsReturnToChildOrDelete) {
889 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
890 return;
891 gfx::Size size(1, 1);
892 ResourceFormat format = RGBA_8888;
894 ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource(
895 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
896 uint8_t data1[4] = {1, 2, 3, 4};
897 child_resource_provider_->CopyToResource(id1, data1, size);
899 ReturnedResourceArray returned_to_child;
900 int child_id =
901 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
903 // Transfer some resources to the parent.
904 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
905 resource_ids_to_transfer.push_back(id1);
906 TransferableResourceArray list;
907 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
908 &list);
909 ASSERT_EQ(1u, list.size());
910 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
912 resource_provider_->ReceiveFromChild(child_id, list);
914 resource_provider_->WaitSyncPointIfNeeded(list[0].id);
915 ResourceProvider::ScopedReadLockGL lock(resource_provider_.get(),
916 list[0].id);
918 resource_provider_->DeclareUsedResourcesFromChild(
919 child_id, ResourceProvider::ResourceIdArray());
920 EXPECT_EQ(0u, returned_to_child.size());
923 EXPECT_EQ(1u, returned_to_child.size());
924 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
927 child_resource_provider_->WaitSyncPointIfNeeded(id1);
928 ResourceProvider::ScopedReadLockGL lock(child_resource_provider_.get(),
929 id1);
930 child_resource_provider_->DeleteResource(id1);
931 EXPECT_EQ(1u, child_resource_provider_->num_resources());
932 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
935 EXPECT_EQ(0u, child_resource_provider_->num_resources());
936 resource_provider_->DestroyChild(child_id);
939 TEST_P(ResourceProviderTest, AllowOverlayTransfersToParent) {
940 // Overlays only supported on the GL path.
941 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
942 return;
944 uint32 sync_point = 0;
945 TextureMailbox mailbox(gpu::Mailbox::Generate(), GL_TEXTURE_2D, sync_point);
946 mailbox.set_allow_overlay(true);
947 scoped_ptr<SingleReleaseCallbackImpl> release_callback =
948 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback));
949 ResourceProvider::ResourceId id1 =
950 child_resource_provider_->CreateResourceFromTextureMailbox(
951 mailbox, release_callback.Pass());
953 TextureMailbox mailbox2(gpu::Mailbox::Generate(), GL_TEXTURE_2D, sync_point);
954 mailbox2.set_allow_overlay(false);
955 scoped_ptr<SingleReleaseCallbackImpl> release_callback2 =
956 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback));
957 ResourceProvider::ResourceId id2 =
958 child_resource_provider_->CreateResourceFromTextureMailbox(
959 mailbox2, release_callback2.Pass());
961 ReturnedResourceArray returned_to_child;
962 int child_id =
963 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
965 // Transfer some resources to the parent.
966 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
967 resource_ids_to_transfer.push_back(id1);
968 resource_ids_to_transfer.push_back(id2);
969 TransferableResourceArray list;
970 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
971 &list);
972 ASSERT_EQ(2u, list.size());
973 resource_provider_->ReceiveFromChild(child_id, list);
974 EXPECT_TRUE(resource_provider_->AllowOverlay(list[0].id));
975 EXPECT_FALSE(resource_provider_->AllowOverlay(list[1].id));
977 resource_provider_->DeclareUsedResourcesFromChild(
978 child_id, ResourceProvider::ResourceIdArray());
980 EXPECT_EQ(2u, returned_to_child.size());
981 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
983 child_resource_provider_->DeleteResource(id1);
984 child_resource_provider_->DeleteResource(id2);
985 EXPECT_EQ(0u, child_resource_provider_->num_resources());
987 resource_provider_->DestroyChild(child_id);
990 TEST_P(ResourceProviderTest, TransferSoftwareResources) {
991 if (GetParam() != ResourceProvider::RESOURCE_TYPE_BITMAP)
992 return;
994 gfx::Size size(1, 1);
995 ResourceFormat format = RGBA_8888;
996 size_t pixel_size = TextureSizeBytes(size, format);
997 ASSERT_EQ(4U, pixel_size);
999 ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource(
1000 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
1001 uint8_t data1[4] = { 1, 2, 3, 4 };
1002 child_resource_provider_->CopyToResource(id1, data1, size);
1004 ResourceProvider::ResourceId id2 = child_resource_provider_->CreateResource(
1005 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
1006 uint8_t data2[4] = { 5, 5, 5, 5 };
1007 child_resource_provider_->CopyToResource(id2, data2, size);
1009 scoped_ptr<SharedBitmap> shared_bitmap(CreateAndFillSharedBitmap(
1010 shared_bitmap_manager_.get(), gfx::Size(1, 1), 0));
1011 SharedBitmap* shared_bitmap_ptr = shared_bitmap.get();
1012 ResourceProvider::ResourceId id3 =
1013 child_resource_provider_->CreateResourceFromTextureMailbox(
1014 TextureMailbox(shared_bitmap_ptr, gfx::Size(1, 1)),
1015 SingleReleaseCallbackImpl::Create(base::Bind(
1016 &SharedBitmapReleaseCallback, base::Passed(&shared_bitmap))));
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 resource_ids_to_transfer.push_back(id2);
1026 resource_ids_to_transfer.push_back(id3);
1027 TransferableResourceArray list;
1028 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1029 &list);
1030 ASSERT_EQ(3u, list.size());
1031 EXPECT_EQ(0u, list[0].mailbox_holder.sync_point);
1032 EXPECT_EQ(0u, list[1].mailbox_holder.sync_point);
1033 EXPECT_EQ(0u, list[2].mailbox_holder.sync_point);
1034 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1035 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
1036 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
1037 resource_provider_->ReceiveFromChild(child_id, list);
1038 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1039 resource_ids_to_transfer);
1042 EXPECT_EQ(3u, resource_provider_->num_resources());
1043 ResourceProvider::ResourceIdMap resource_map =
1044 resource_provider_->GetChildToParentMap(child_id);
1045 ResourceProvider::ResourceId mapped_id1 = resource_map[id1];
1046 ResourceProvider::ResourceId mapped_id2 = resource_map[id2];
1047 ResourceProvider::ResourceId mapped_id3 = resource_map[id3];
1048 EXPECT_NE(0u, mapped_id1);
1049 EXPECT_NE(0u, mapped_id2);
1050 EXPECT_NE(0u, mapped_id3);
1051 EXPECT_FALSE(resource_provider_->InUseByConsumer(id1));
1052 EXPECT_FALSE(resource_provider_->InUseByConsumer(id2));
1053 EXPECT_FALSE(resource_provider_->InUseByConsumer(id3));
1055 uint8_t result[4] = { 0 };
1056 GetResourcePixels(
1057 resource_provider_.get(), context(), mapped_id1, size, format, result);
1058 EXPECT_EQ(0, memcmp(data1, result, pixel_size));
1060 GetResourcePixels(
1061 resource_provider_.get(), context(), mapped_id2, size, format, result);
1062 EXPECT_EQ(0, memcmp(data2, result, pixel_size));
1065 // Check that transfering again the same resource from the child to the
1066 // parent works.
1067 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1068 resource_ids_to_transfer.push_back(id1);
1069 resource_ids_to_transfer.push_back(id2);
1070 TransferableResourceArray list;
1071 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1072 &list);
1073 EXPECT_EQ(2u, list.size());
1074 EXPECT_EQ(id1, list[0].id);
1075 EXPECT_EQ(id2, list[1].id);
1076 ReturnedResourceArray returned;
1077 TransferableResource::ReturnResources(list, &returned);
1078 child_resource_provider_->ReceiveReturnsFromParent(returned);
1079 // ids were exported twice, we returned them only once, they should still
1080 // be in-use.
1081 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1082 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
1085 EXPECT_EQ(0u, returned_to_child.size());
1087 // Transfer resources back from the parent to the child. Set no resources as
1088 // being in use.
1089 ResourceProvider::ResourceIdArray no_resources;
1090 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
1092 ASSERT_EQ(3u, returned_to_child.size());
1093 EXPECT_EQ(0u, returned_to_child[0].sync_point);
1094 EXPECT_EQ(0u, returned_to_child[1].sync_point);
1095 EXPECT_EQ(0u, returned_to_child[2].sync_point);
1096 std::set<ResourceProvider::ResourceId> expected_ids;
1097 expected_ids.insert(id1);
1098 expected_ids.insert(id2);
1099 expected_ids.insert(id3);
1100 std::set<ResourceProvider::ResourceId> returned_ids;
1101 for (unsigned i = 0; i < 3; i++)
1102 returned_ids.insert(returned_to_child[i].id);
1103 EXPECT_EQ(expected_ids, returned_ids);
1104 EXPECT_FALSE(returned_to_child[0].lost);
1105 EXPECT_FALSE(returned_to_child[1].lost);
1106 EXPECT_FALSE(returned_to_child[2].lost);
1107 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
1108 returned_to_child.clear();
1110 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id1));
1111 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id2));
1112 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id3));
1115 ResourceProvider::ScopedReadLockSoftware lock(
1116 child_resource_provider_.get(), id1);
1117 const SkBitmap* sk_bitmap = lock.sk_bitmap();
1118 EXPECT_EQ(sk_bitmap->width(), size.width());
1119 EXPECT_EQ(sk_bitmap->height(), size.height());
1120 EXPECT_EQ(0, memcmp(data1, sk_bitmap->getPixels(), pixel_size));
1123 ResourceProvider::ScopedReadLockSoftware lock(
1124 child_resource_provider_.get(), id2);
1125 const SkBitmap* sk_bitmap = lock.sk_bitmap();
1126 EXPECT_EQ(sk_bitmap->width(), size.width());
1127 EXPECT_EQ(sk_bitmap->height(), size.height());
1128 EXPECT_EQ(0, memcmp(data2, sk_bitmap->getPixels(), pixel_size));
1131 // Transfer resources to the parent again.
1132 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1133 resource_ids_to_transfer.push_back(id1);
1134 resource_ids_to_transfer.push_back(id2);
1135 resource_ids_to_transfer.push_back(id3);
1136 TransferableResourceArray list;
1137 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1138 &list);
1139 ASSERT_EQ(3u, list.size());
1140 EXPECT_EQ(id1, list[0].id);
1141 EXPECT_EQ(id2, list[1].id);
1142 EXPECT_EQ(id3, list[2].id);
1143 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1144 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
1145 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
1146 resource_provider_->ReceiveFromChild(child_id, list);
1147 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1148 resource_ids_to_transfer);
1151 EXPECT_EQ(0u, returned_to_child.size());
1153 EXPECT_EQ(3u, resource_provider_->num_resources());
1154 resource_provider_->DestroyChild(child_id);
1155 EXPECT_EQ(0u, resource_provider_->num_resources());
1157 ASSERT_EQ(3u, returned_to_child.size());
1158 EXPECT_EQ(0u, returned_to_child[0].sync_point);
1159 EXPECT_EQ(0u, returned_to_child[1].sync_point);
1160 EXPECT_EQ(0u, returned_to_child[2].sync_point);
1161 std::set<ResourceProvider::ResourceId> expected_ids;
1162 expected_ids.insert(id1);
1163 expected_ids.insert(id2);
1164 expected_ids.insert(id3);
1165 std::set<ResourceProvider::ResourceId> returned_ids;
1166 for (unsigned i = 0; i < 3; i++)
1167 returned_ids.insert(returned_to_child[i].id);
1168 EXPECT_EQ(expected_ids, returned_ids);
1169 EXPECT_FALSE(returned_to_child[0].lost);
1170 EXPECT_FALSE(returned_to_child[1].lost);
1171 EXPECT_FALSE(returned_to_child[2].lost);
1174 TEST_P(ResourceProviderTest, TransferGLToSoftware) {
1175 if (GetParam() != ResourceProvider::RESOURCE_TYPE_BITMAP)
1176 return;
1178 scoped_ptr<ResourceProviderContext> child_context_owned(
1179 ResourceProviderContext::Create(shared_data_.get()));
1181 FakeOutputSurfaceClient child_output_surface_client;
1182 scoped_ptr<OutputSurface> child_output_surface(
1183 FakeOutputSurface::Create3d(child_context_owned.Pass()));
1184 CHECK(child_output_surface->BindToClient(&child_output_surface_client));
1186 scoped_ptr<ResourceProvider> child_resource_provider(
1187 ResourceProvider::Create(child_output_surface.get(),
1188 shared_bitmap_manager_.get(),
1189 gpu_memory_buffer_manager_.get(),
1190 NULL,
1192 false,
1193 1));
1195 gfx::Size size(1, 1);
1196 ResourceFormat format = RGBA_8888;
1197 size_t pixel_size = TextureSizeBytes(size, format);
1198 ASSERT_EQ(4U, pixel_size);
1200 ResourceProvider::ResourceId id1 = child_resource_provider->CreateResource(
1201 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
1202 uint8_t data1[4] = { 1, 2, 3, 4 };
1203 child_resource_provider->CopyToResource(id1, data1, size);
1205 ReturnedResourceArray returned_to_child;
1206 int child_id =
1207 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1209 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1210 resource_ids_to_transfer.push_back(id1);
1211 TransferableResourceArray list;
1212 child_resource_provider->PrepareSendToParent(resource_ids_to_transfer,
1213 &list);
1214 ASSERT_EQ(1u, list.size());
1215 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
1216 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
1217 list[0].mailbox_holder.texture_target);
1218 EXPECT_TRUE(child_resource_provider->InUseByConsumer(id1));
1219 resource_provider_->ReceiveFromChild(child_id, list);
1222 EXPECT_EQ(0u, resource_provider_->num_resources());
1223 ASSERT_EQ(1u, returned_to_child.size());
1224 EXPECT_EQ(returned_to_child[0].id, id1);
1225 ResourceProvider::ResourceIdMap resource_map =
1226 resource_provider_->GetChildToParentMap(child_id);
1227 ResourceProvider::ResourceId mapped_id1 = resource_map[id1];
1228 EXPECT_EQ(0u, mapped_id1);
1230 resource_provider_->DestroyChild(child_id);
1231 EXPECT_EQ(0u, resource_provider_->num_resources());
1233 ASSERT_EQ(1u, returned_to_child.size());
1234 EXPECT_FALSE(returned_to_child[0].lost);
1237 TEST_P(ResourceProviderTest, TransferInvalidSoftware) {
1238 if (GetParam() != ResourceProvider::RESOURCE_TYPE_BITMAP)
1239 return;
1241 gfx::Size size(1, 1);
1242 ResourceFormat format = RGBA_8888;
1243 size_t pixel_size = TextureSizeBytes(size, format);
1244 ASSERT_EQ(4U, pixel_size);
1246 ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource(
1247 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
1248 uint8_t data1[4] = { 1, 2, 3, 4 };
1249 child_resource_provider_->CopyToResource(id1, data1, size);
1251 ReturnedResourceArray returned_to_child;
1252 int child_id =
1253 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1255 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1256 resource_ids_to_transfer.push_back(id1);
1257 TransferableResourceArray list;
1258 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1259 &list);
1260 ASSERT_EQ(1u, list.size());
1261 // Make invalid.
1262 list[0].mailbox_holder.mailbox.name[1] = 5;
1263 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1264 resource_provider_->ReceiveFromChild(child_id, list);
1267 EXPECT_EQ(1u, resource_provider_->num_resources());
1268 EXPECT_EQ(0u, returned_to_child.size());
1270 ResourceProvider::ResourceIdMap resource_map =
1271 resource_provider_->GetChildToParentMap(child_id);
1272 ResourceProvider::ResourceId mapped_id1 = resource_map[id1];
1273 EXPECT_NE(0u, mapped_id1);
1275 ResourceProvider::ScopedReadLockSoftware lock(resource_provider_.get(),
1276 mapped_id1);
1277 EXPECT_FALSE(lock.valid());
1280 resource_provider_->DestroyChild(child_id);
1281 EXPECT_EQ(0u, resource_provider_->num_resources());
1283 ASSERT_EQ(1u, returned_to_child.size());
1284 EXPECT_FALSE(returned_to_child[0].lost);
1287 TEST_P(ResourceProviderTest, DeleteExportedResources) {
1288 gfx::Size size(1, 1);
1289 ResourceFormat format = RGBA_8888;
1290 size_t pixel_size = TextureSizeBytes(size, format);
1291 ASSERT_EQ(4U, pixel_size);
1293 ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource(
1294 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
1295 uint8_t data1[4] = { 1, 2, 3, 4 };
1296 child_resource_provider_->CopyToResource(id1, data1, size);
1298 ResourceProvider::ResourceId id2 = child_resource_provider_->CreateResource(
1299 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
1300 uint8_t data2[4] = {5, 5, 5, 5};
1301 child_resource_provider_->CopyToResource(id2, data2, size);
1303 ReturnedResourceArray returned_to_child;
1304 int child_id =
1305 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1307 // Transfer some resources to the parent.
1308 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1309 resource_ids_to_transfer.push_back(id1);
1310 resource_ids_to_transfer.push_back(id2);
1311 TransferableResourceArray list;
1312 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1313 &list);
1314 ASSERT_EQ(2u, list.size());
1315 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) {
1316 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
1317 EXPECT_NE(0u, list[1].mailbox_holder.sync_point);
1319 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1320 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
1321 resource_provider_->ReceiveFromChild(child_id, list);
1322 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1323 resource_ids_to_transfer);
1326 EXPECT_EQ(2u, resource_provider_->num_resources());
1327 ResourceProvider::ResourceIdMap resource_map =
1328 resource_provider_->GetChildToParentMap(child_id);
1329 ResourceProvider::ResourceId mapped_id1 = resource_map[id1];
1330 ResourceProvider::ResourceId mapped_id2 = resource_map[id2];
1331 EXPECT_NE(0u, mapped_id1);
1332 EXPECT_NE(0u, mapped_id2);
1333 EXPECT_FALSE(resource_provider_->InUseByConsumer(id1));
1334 EXPECT_FALSE(resource_provider_->InUseByConsumer(id2));
1337 // The parent transfers the resources to the grandparent.
1338 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1339 resource_ids_to_transfer.push_back(mapped_id1);
1340 resource_ids_to_transfer.push_back(mapped_id2);
1341 TransferableResourceArray list;
1342 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
1344 ASSERT_EQ(2u, list.size());
1345 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) {
1346 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
1347 EXPECT_NE(0u, list[1].mailbox_holder.sync_point);
1349 EXPECT_TRUE(resource_provider_->InUseByConsumer(id1));
1350 EXPECT_TRUE(resource_provider_->InUseByConsumer(id2));
1352 // Release the resource in the parent. Set no resources as being in use. The
1353 // resources are exported so that can't be transferred back yet.
1354 ResourceProvider::ResourceIdArray no_resources;
1355 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
1357 EXPECT_EQ(0u, returned_to_child.size());
1358 EXPECT_EQ(2u, resource_provider_->num_resources());
1360 // Return the resources from the grandparent to the parent. They should be
1361 // returned to the child then.
1362 EXPECT_EQ(2u, list.size());
1363 EXPECT_EQ(mapped_id1, list[0].id);
1364 EXPECT_EQ(mapped_id2, list[1].id);
1365 ReturnedResourceArray returned;
1366 TransferableResource::ReturnResources(list, &returned);
1367 resource_provider_->ReceiveReturnsFromParent(returned);
1369 EXPECT_EQ(0u, resource_provider_->num_resources());
1370 ASSERT_EQ(2u, returned_to_child.size());
1371 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) {
1372 EXPECT_NE(0u, returned_to_child[0].sync_point);
1373 EXPECT_NE(0u, returned_to_child[1].sync_point);
1375 EXPECT_FALSE(returned_to_child[0].lost);
1376 EXPECT_FALSE(returned_to_child[1].lost);
1380 TEST_P(ResourceProviderTest, DestroyChildWithExportedResources) {
1381 gfx::Size size(1, 1);
1382 ResourceFormat format = RGBA_8888;
1383 size_t pixel_size = TextureSizeBytes(size, format);
1384 ASSERT_EQ(4U, pixel_size);
1386 ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource(
1387 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
1388 uint8_t data1[4] = {1, 2, 3, 4};
1389 child_resource_provider_->CopyToResource(id1, data1, size);
1391 ResourceProvider::ResourceId id2 = child_resource_provider_->CreateResource(
1392 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
1393 uint8_t data2[4] = {5, 5, 5, 5};
1394 child_resource_provider_->CopyToResource(id2, data2, size);
1396 ReturnedResourceArray returned_to_child;
1397 int child_id =
1398 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1400 // Transfer some resources to the parent.
1401 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1402 resource_ids_to_transfer.push_back(id1);
1403 resource_ids_to_transfer.push_back(id2);
1404 TransferableResourceArray list;
1405 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1406 &list);
1407 ASSERT_EQ(2u, list.size());
1408 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) {
1409 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
1410 EXPECT_NE(0u, list[1].mailbox_holder.sync_point);
1412 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1413 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
1414 resource_provider_->ReceiveFromChild(child_id, list);
1415 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1416 resource_ids_to_transfer);
1419 EXPECT_EQ(2u, resource_provider_->num_resources());
1420 ResourceProvider::ResourceIdMap resource_map =
1421 resource_provider_->GetChildToParentMap(child_id);
1422 ResourceProvider::ResourceId mapped_id1 = resource_map[id1];
1423 ResourceProvider::ResourceId mapped_id2 = resource_map[id2];
1424 EXPECT_NE(0u, mapped_id1);
1425 EXPECT_NE(0u, mapped_id2);
1426 EXPECT_FALSE(resource_provider_->InUseByConsumer(id1));
1427 EXPECT_FALSE(resource_provider_->InUseByConsumer(id2));
1430 // The parent transfers the resources to the grandparent.
1431 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1432 resource_ids_to_transfer.push_back(mapped_id1);
1433 resource_ids_to_transfer.push_back(mapped_id2);
1434 TransferableResourceArray list;
1435 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
1437 ASSERT_EQ(2u, list.size());
1438 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) {
1439 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
1440 EXPECT_NE(0u, list[1].mailbox_holder.sync_point);
1442 EXPECT_TRUE(resource_provider_->InUseByConsumer(id1));
1443 EXPECT_TRUE(resource_provider_->InUseByConsumer(id2));
1445 // Release the resource in the parent. Set no resources as being in use. The
1446 // resources are exported so that can't be transferred back yet.
1447 ResourceProvider::ResourceIdArray no_resources;
1448 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
1450 // Destroy the child, the resources should not be returned yet.
1451 EXPECT_EQ(0u, returned_to_child.size());
1452 EXPECT_EQ(2u, resource_provider_->num_resources());
1454 resource_provider_->DestroyChild(child_id);
1456 EXPECT_EQ(2u, resource_provider_->num_resources());
1457 ASSERT_EQ(0u, returned_to_child.size());
1459 // Return a resource from the grandparent, it should be returned at this
1460 // point.
1461 EXPECT_EQ(2u, list.size());
1462 EXPECT_EQ(mapped_id1, list[0].id);
1463 EXPECT_EQ(mapped_id2, list[1].id);
1464 TransferableResourceArray return_list;
1465 return_list.push_back(list[1]);
1466 list.pop_back();
1467 ReturnedResourceArray returned;
1468 TransferableResource::ReturnResources(return_list, &returned);
1469 resource_provider_->ReceiveReturnsFromParent(returned);
1471 EXPECT_EQ(1u, resource_provider_->num_resources());
1472 ASSERT_EQ(1u, returned_to_child.size());
1473 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) {
1474 EXPECT_NE(0u, returned_to_child[0].sync_point);
1476 EXPECT_FALSE(returned_to_child[0].lost);
1477 returned_to_child.clear();
1479 // Destroy the parent resource provider. The resource that's left should be
1480 // lost at this point, and returned.
1481 resource_provider_ = nullptr;
1482 ASSERT_EQ(1u, returned_to_child.size());
1483 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) {
1484 EXPECT_NE(0u, returned_to_child[0].sync_point);
1486 EXPECT_TRUE(returned_to_child[0].lost);
1490 TEST_P(ResourceProviderTest, DeleteTransferredResources) {
1491 gfx::Size size(1, 1);
1492 ResourceFormat format = RGBA_8888;
1493 size_t pixel_size = TextureSizeBytes(size, format);
1494 ASSERT_EQ(4U, pixel_size);
1496 ResourceProvider::ResourceId id = child_resource_provider_->CreateResource(
1497 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
1498 uint8_t data[4] = { 1, 2, 3, 4 };
1499 child_resource_provider_->CopyToResource(id, data, size);
1501 ReturnedResourceArray returned_to_child;
1502 int child_id =
1503 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1505 // Transfer some resource to the parent.
1506 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1507 resource_ids_to_transfer.push_back(id);
1508 TransferableResourceArray list;
1509 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1510 &list);
1511 ASSERT_EQ(1u, list.size());
1512 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
1513 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
1514 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id));
1515 resource_provider_->ReceiveFromChild(child_id, list);
1516 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1517 resource_ids_to_transfer);
1520 // Delete textures in the child, while they are transfered.
1521 child_resource_provider_->DeleteResource(id);
1522 EXPECT_EQ(1u, child_resource_provider_->num_resources());
1524 EXPECT_EQ(0u, returned_to_child.size());
1526 // Transfer resources back from the parent to the child. Set no resources as
1527 // being in use.
1528 ResourceProvider::ResourceIdArray no_resources;
1529 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
1531 ASSERT_EQ(1u, returned_to_child.size());
1532 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
1533 EXPECT_NE(0u, returned_to_child[0].sync_point);
1534 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
1536 EXPECT_EQ(0u, child_resource_provider_->num_resources());
1539 TEST_P(ResourceProviderTest, UnuseTransferredResources) {
1540 gfx::Size size(1, 1);
1541 ResourceFormat format = RGBA_8888;
1542 size_t pixel_size = TextureSizeBytes(size, format);
1543 ASSERT_EQ(4U, pixel_size);
1545 ResourceProvider::ResourceId id = child_resource_provider_->CreateResource(
1546 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
1547 uint8_t data[4] = {1, 2, 3, 4};
1548 child_resource_provider_->CopyToResource(id, data, size);
1550 ReturnedResourceArray returned_to_child;
1551 int child_id =
1552 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1553 const ResourceProvider::ResourceIdMap& map =
1554 resource_provider_->GetChildToParentMap(child_id);
1556 // Transfer some resource to the parent.
1557 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1558 resource_ids_to_transfer.push_back(id);
1559 TransferableResourceArray list;
1560 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1561 &list);
1562 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id));
1563 resource_provider_->ReceiveFromChild(child_id, list);
1564 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1565 resource_ids_to_transfer);
1567 TransferableResourceArray sent_to_top_level;
1569 // Parent transfers to top-level.
1570 ASSERT_TRUE(map.find(id) != map.end());
1571 ResourceProvider::ResourceId parent_id = map.find(id)->second;
1572 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1573 resource_ids_to_transfer.push_back(parent_id);
1574 resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1575 &sent_to_top_level);
1576 EXPECT_TRUE(resource_provider_->InUseByConsumer(parent_id));
1579 // Stop using resource.
1580 ResourceProvider::ResourceIdArray empty;
1581 resource_provider_->DeclareUsedResourcesFromChild(child_id, empty);
1582 // Resource is not yet returned to the child, since it's in use by the
1583 // top-level.
1584 EXPECT_TRUE(returned_to_child.empty());
1587 // Send the resource to the parent again.
1588 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1589 resource_ids_to_transfer.push_back(id);
1590 TransferableResourceArray list;
1591 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1592 &list);
1593 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id));
1594 resource_provider_->ReceiveFromChild(child_id, list);
1595 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1596 resource_ids_to_transfer);
1599 // Receive returns back from top-level.
1600 ReturnedResourceArray returned;
1601 TransferableResource::ReturnResources(sent_to_top_level, &returned);
1602 resource_provider_->ReceiveReturnsFromParent(returned);
1603 // Resource is still not yet returned to the child, since it's declared used
1604 // in the parent.
1605 EXPECT_TRUE(returned_to_child.empty());
1606 ASSERT_TRUE(map.find(id) != map.end());
1607 ResourceProvider::ResourceId parent_id = map.find(id)->second;
1608 EXPECT_FALSE(resource_provider_->InUseByConsumer(parent_id));
1611 sent_to_top_level.clear();
1612 // Parent transfers again to top-level.
1613 ASSERT_TRUE(map.find(id) != map.end());
1614 ResourceProvider::ResourceId parent_id = map.find(id)->second;
1615 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1616 resource_ids_to_transfer.push_back(parent_id);
1617 resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1618 &sent_to_top_level);
1619 EXPECT_TRUE(resource_provider_->InUseByConsumer(parent_id));
1622 // Receive returns back from top-level.
1623 ReturnedResourceArray returned;
1624 TransferableResource::ReturnResources(sent_to_top_level, &returned);
1625 resource_provider_->ReceiveReturnsFromParent(returned);
1626 // Resource is still not yet returned to the child, since it's still
1627 // declared used in the parent.
1628 EXPECT_TRUE(returned_to_child.empty());
1629 ASSERT_TRUE(map.find(id) != map.end());
1630 ResourceProvider::ResourceId parent_id = map.find(id)->second;
1631 EXPECT_FALSE(resource_provider_->InUseByConsumer(parent_id));
1634 // Stop using resource.
1635 ResourceProvider::ResourceIdArray empty;
1636 resource_provider_->DeclareUsedResourcesFromChild(child_id, empty);
1637 // Resource should have been returned to the child, since it's no longer in
1638 // use by the top-level.
1639 ASSERT_EQ(1u, returned_to_child.size());
1640 EXPECT_EQ(id, returned_to_child[0].id);
1641 EXPECT_EQ(2, returned_to_child[0].count);
1642 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
1643 returned_to_child.clear();
1644 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id));
1648 class ResourceProviderTestTextureFilters : public ResourceProviderTest {
1649 public:
1650 static void RunTest(GLenum child_filter, GLenum parent_filter) {
1651 scoped_ptr<TextureStateTrackingContext> child_context_owned(
1652 new TextureStateTrackingContext);
1653 TextureStateTrackingContext* child_context = child_context_owned.get();
1655 FakeOutputSurfaceClient child_output_surface_client;
1656 scoped_ptr<OutputSurface> child_output_surface(
1657 FakeOutputSurface::Create3d(child_context_owned.Pass()));
1658 CHECK(child_output_surface->BindToClient(&child_output_surface_client));
1659 scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
1660 new TestSharedBitmapManager());
1662 scoped_ptr<ResourceProvider> child_resource_provider(
1663 ResourceProvider::Create(child_output_surface.get(),
1664 shared_bitmap_manager.get(),
1665 NULL,
1666 NULL,
1668 false,
1669 1));
1671 scoped_ptr<TextureStateTrackingContext> parent_context_owned(
1672 new TextureStateTrackingContext);
1673 TextureStateTrackingContext* parent_context = parent_context_owned.get();
1675 FakeOutputSurfaceClient parent_output_surface_client;
1676 scoped_ptr<OutputSurface> parent_output_surface(
1677 FakeOutputSurface::Create3d(parent_context_owned.Pass()));
1678 CHECK(parent_output_surface->BindToClient(&parent_output_surface_client));
1680 scoped_ptr<ResourceProvider> parent_resource_provider(
1681 ResourceProvider::Create(parent_output_surface.get(),
1682 shared_bitmap_manager.get(),
1683 NULL,
1684 NULL,
1686 false,
1687 1));
1689 gfx::Size size(1, 1);
1690 ResourceFormat format = RGBA_8888;
1691 int child_texture_id = 1;
1692 int parent_texture_id = 2;
1694 size_t pixel_size = TextureSizeBytes(size, format);
1695 ASSERT_EQ(4U, pixel_size);
1697 ResourceProvider::ResourceId id = child_resource_provider->CreateResource(
1698 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE,
1699 format);
1701 // The new texture is created with GL_LINEAR.
1702 EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, child_texture_id))
1703 .Times(2); // Once to create and once to allocate.
1704 EXPECT_CALL(*child_context,
1705 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
1706 EXPECT_CALL(*child_context,
1707 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
1708 EXPECT_CALL(
1709 *child_context,
1710 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
1711 EXPECT_CALL(
1712 *child_context,
1713 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
1714 EXPECT_CALL(*child_context,
1715 texParameteri(GL_TEXTURE_2D,
1716 GL_TEXTURE_POOL_CHROMIUM,
1717 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM));
1718 child_resource_provider->AllocateForTesting(id);
1719 Mock::VerifyAndClearExpectations(child_context);
1721 uint8_t data[4] = { 1, 2, 3, 4 };
1723 EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, child_texture_id));
1724 child_resource_provider->CopyToResource(id, data, size);
1725 Mock::VerifyAndClearExpectations(child_context);
1727 // The texture is set to |child_filter| in the child.
1728 EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, child_texture_id));
1729 if (child_filter != GL_LINEAR) {
1730 EXPECT_CALL(
1731 *child_context,
1732 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, child_filter));
1733 EXPECT_CALL(
1734 *child_context,
1735 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, child_filter));
1737 SetResourceFilter(child_resource_provider.get(), id, child_filter);
1738 Mock::VerifyAndClearExpectations(child_context);
1740 ReturnedResourceArray returned_to_child;
1741 int child_id = parent_resource_provider->CreateChild(
1742 GetReturnCallback(&returned_to_child));
1744 // Transfer some resource to the parent.
1745 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1746 resource_ids_to_transfer.push_back(id);
1747 TransferableResourceArray list;
1749 EXPECT_CALL(*child_context,
1750 produceTextureDirectCHROMIUM(_, GL_TEXTURE_2D, _));
1751 EXPECT_CALL(*child_context, insertSyncPoint());
1752 child_resource_provider->PrepareSendToParent(resource_ids_to_transfer,
1753 &list);
1754 Mock::VerifyAndClearExpectations(child_context);
1756 ASSERT_EQ(1u, list.size());
1757 EXPECT_EQ(static_cast<unsigned>(child_filter), list[0].filter);
1759 EXPECT_CALL(*parent_context,
1760 createAndConsumeTextureCHROMIUM(GL_TEXTURE_2D, _))
1761 .WillOnce(Return(parent_texture_id));
1763 parent_resource_provider->ReceiveFromChild(child_id, list);
1765 parent_resource_provider->WaitSyncPointIfNeeded(list[0].id);
1766 ResourceProvider::ScopedReadLockGL lock(parent_resource_provider.get(),
1767 list[0].id);
1769 Mock::VerifyAndClearExpectations(parent_context);
1771 parent_resource_provider->DeclareUsedResourcesFromChild(
1772 child_id, resource_ids_to_transfer);
1773 Mock::VerifyAndClearExpectations(parent_context);
1775 ResourceProvider::ResourceIdMap resource_map =
1776 parent_resource_provider->GetChildToParentMap(child_id);
1777 ResourceProvider::ResourceId mapped_id = resource_map[id];
1778 EXPECT_NE(0u, mapped_id);
1780 // The texture is set to |parent_filter| in the parent.
1781 EXPECT_CALL(*parent_context, bindTexture(GL_TEXTURE_2D, parent_texture_id));
1782 EXPECT_CALL(
1783 *parent_context,
1784 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, parent_filter));
1785 EXPECT_CALL(
1786 *parent_context,
1787 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, parent_filter));
1788 SetResourceFilter(parent_resource_provider.get(), mapped_id, parent_filter);
1789 Mock::VerifyAndClearExpectations(parent_context);
1791 // The texture should be reset to |child_filter| in the parent when it is
1792 // returned, since that is how it was received.
1793 EXPECT_CALL(*parent_context, bindTexture(GL_TEXTURE_2D, parent_texture_id));
1794 EXPECT_CALL(
1795 *parent_context,
1796 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, child_filter));
1797 EXPECT_CALL(
1798 *parent_context,
1799 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, child_filter));
1802 EXPECT_EQ(0u, returned_to_child.size());
1804 // Transfer resources back from the parent to the child. Set no resources
1805 // as being in use.
1806 ResourceProvider::ResourceIdArray no_resources;
1807 EXPECT_CALL(*parent_context, insertSyncPoint());
1808 parent_resource_provider->DeclareUsedResourcesFromChild(child_id,
1809 no_resources);
1810 Mock::VerifyAndClearExpectations(parent_context);
1812 ASSERT_EQ(1u, returned_to_child.size());
1813 child_resource_provider->ReceiveReturnsFromParent(returned_to_child);
1816 // The child remembers the texture filter is set to |child_filter|.
1817 EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, child_texture_id));
1818 SetResourceFilter(child_resource_provider.get(), id, child_filter);
1819 Mock::VerifyAndClearExpectations(child_context);
1823 TEST_P(ResourceProviderTest, TextureFilters_ChildNearestParentLinear) {
1824 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
1825 return;
1826 ResourceProviderTestTextureFilters::RunTest(GL_NEAREST, GL_LINEAR);
1829 TEST_P(ResourceProviderTest, TextureFilters_ChildLinearParentNearest) {
1830 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
1831 return;
1832 ResourceProviderTestTextureFilters::RunTest(GL_LINEAR, GL_NEAREST);
1835 TEST_P(ResourceProviderTest, TransferMailboxResources) {
1836 // Other mailbox transfers tested elsewhere.
1837 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
1838 return;
1839 unsigned texture = context()->createTexture();
1840 context()->bindTexture(GL_TEXTURE_2D, texture);
1841 uint8_t data[4] = { 1, 2, 3, 4 };
1842 context()->texImage2D(
1843 GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &data);
1844 gpu::Mailbox mailbox;
1845 context()->genMailboxCHROMIUM(mailbox.name);
1846 context()->produceTextureDirectCHROMIUM(texture, GL_TEXTURE_2D, mailbox.name);
1847 uint32 sync_point = context()->insertSyncPoint();
1849 // All the logic below assumes that the sync points are all positive.
1850 EXPECT_LT(0u, sync_point);
1852 uint32 release_sync_point = 0;
1853 bool lost_resource = false;
1854 BlockingTaskRunner* main_thread_task_runner = NULL;
1855 ReleaseCallbackImpl callback = base::Bind(ReleaseCallback,
1856 &release_sync_point,
1857 &lost_resource,
1858 &main_thread_task_runner);
1859 ResourceProvider::ResourceId resource =
1860 resource_provider_->CreateResourceFromTextureMailbox(
1861 TextureMailbox(mailbox, GL_TEXTURE_2D, sync_point),
1862 SingleReleaseCallbackImpl::Create(callback));
1863 EXPECT_EQ(1u, context()->NumTextures());
1864 EXPECT_EQ(0u, release_sync_point);
1866 // Transfer the resource, expect the sync points to be consistent.
1867 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1868 resource_ids_to_transfer.push_back(resource);
1869 TransferableResourceArray list;
1870 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
1871 ASSERT_EQ(1u, list.size());
1872 EXPECT_LE(sync_point, list[0].mailbox_holder.sync_point);
1873 EXPECT_EQ(0,
1874 memcmp(mailbox.name,
1875 list[0].mailbox_holder.mailbox.name,
1876 sizeof(mailbox.name)));
1877 EXPECT_EQ(0u, release_sync_point);
1879 context()->waitSyncPoint(list[0].mailbox_holder.sync_point);
1880 unsigned other_texture =
1881 context()->createAndConsumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
1882 uint8_t test_data[4] = { 0 };
1883 context()->GetPixels(
1884 gfx::Size(1, 1), RGBA_8888, test_data);
1885 EXPECT_EQ(0, memcmp(data, test_data, sizeof(data)));
1887 context()->produceTextureDirectCHROMIUM(other_texture, GL_TEXTURE_2D,
1888 mailbox.name);
1889 context()->deleteTexture(other_texture);
1890 list[0].mailbox_holder.sync_point = context()->insertSyncPoint();
1891 EXPECT_LT(0u, list[0].mailbox_holder.sync_point);
1893 // Receive the resource, then delete it, expect the sync points to be
1894 // consistent.
1895 ReturnedResourceArray returned;
1896 TransferableResource::ReturnResources(list, &returned);
1897 resource_provider_->ReceiveReturnsFromParent(returned);
1898 EXPECT_EQ(1u, context()->NumTextures());
1899 EXPECT_EQ(0u, release_sync_point);
1901 resource_provider_->DeleteResource(resource);
1902 EXPECT_LE(list[0].mailbox_holder.sync_point, release_sync_point);
1903 EXPECT_FALSE(lost_resource);
1904 EXPECT_EQ(main_thread_task_runner_.get(), main_thread_task_runner);
1907 // We're going to do the same thing as above, but testing the case where we
1908 // delete the resource before we receive it back.
1909 sync_point = release_sync_point;
1910 EXPECT_LT(0u, sync_point);
1911 release_sync_point = 0;
1912 resource = resource_provider_->CreateResourceFromTextureMailbox(
1913 TextureMailbox(mailbox, GL_TEXTURE_2D, sync_point),
1914 SingleReleaseCallbackImpl::Create(callback));
1915 EXPECT_EQ(1u, context()->NumTextures());
1916 EXPECT_EQ(0u, release_sync_point);
1918 // Transfer the resource, expect the sync points to be consistent.
1919 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1920 resource_ids_to_transfer.push_back(resource);
1921 TransferableResourceArray list;
1922 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
1923 ASSERT_EQ(1u, list.size());
1924 EXPECT_LE(sync_point, list[0].mailbox_holder.sync_point);
1925 EXPECT_EQ(0,
1926 memcmp(mailbox.name,
1927 list[0].mailbox_holder.mailbox.name,
1928 sizeof(mailbox.name)));
1929 EXPECT_EQ(0u, release_sync_point);
1931 context()->waitSyncPoint(list[0].mailbox_holder.sync_point);
1932 unsigned other_texture =
1933 context()->createAndConsumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
1934 uint8_t test_data[4] = { 0 };
1935 context()->GetPixels(
1936 gfx::Size(1, 1), RGBA_8888, test_data);
1937 EXPECT_EQ(0, memcmp(data, test_data, sizeof(data)));
1939 context()->produceTextureDirectCHROMIUM(other_texture, GL_TEXTURE_2D,
1940 mailbox.name);
1941 context()->deleteTexture(other_texture);
1942 list[0].mailbox_holder.sync_point = context()->insertSyncPoint();
1943 EXPECT_LT(0u, list[0].mailbox_holder.sync_point);
1945 // Delete the resource, which shouldn't do anything.
1946 resource_provider_->DeleteResource(resource);
1947 EXPECT_EQ(1u, context()->NumTextures());
1948 EXPECT_EQ(0u, release_sync_point);
1950 // Then receive the resource which should release the mailbox, expect the
1951 // sync points to be consistent.
1952 ReturnedResourceArray returned;
1953 TransferableResource::ReturnResources(list, &returned);
1954 resource_provider_->ReceiveReturnsFromParent(returned);
1955 EXPECT_LE(list[0].mailbox_holder.sync_point, release_sync_point);
1956 EXPECT_FALSE(lost_resource);
1957 EXPECT_EQ(main_thread_task_runner_.get(), main_thread_task_runner);
1960 context()->waitSyncPoint(release_sync_point);
1961 texture =
1962 context()->createAndConsumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
1963 context()->deleteTexture(texture);
1966 TEST_P(ResourceProviderTest, LostResourceInParent) {
1967 gfx::Size size(1, 1);
1968 ResourceFormat format = RGBA_8888;
1969 ResourceProvider::ResourceId resource =
1970 child_resource_provider_->CreateResource(
1971 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE,
1972 format);
1973 child_resource_provider_->AllocateForTesting(resource);
1974 // Expect a GL resource to be lost.
1975 bool should_lose_resource =
1976 GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE;
1978 ReturnedResourceArray returned_to_child;
1979 int child_id =
1980 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1982 // Transfer the resource to the parent.
1983 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1984 resource_ids_to_transfer.push_back(resource);
1985 TransferableResourceArray list;
1986 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1987 &list);
1988 EXPECT_EQ(1u, list.size());
1990 resource_provider_->ReceiveFromChild(child_id, list);
1991 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1992 resource_ids_to_transfer);
1995 // Lose the output surface in the parent.
1996 resource_provider_->DidLoseOutputSurface();
1999 EXPECT_EQ(0u, returned_to_child.size());
2001 // Transfer resources back from the parent to the child. Set no resources as
2002 // being in use.
2003 ResourceProvider::ResourceIdArray no_resources;
2004 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
2006 // Expect a GL resource to be lost.
2007 ASSERT_EQ(1u, returned_to_child.size());
2008 EXPECT_EQ(should_lose_resource, returned_to_child[0].lost);
2009 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
2010 returned_to_child.clear();
2013 // A GL resource should be lost.
2014 EXPECT_EQ(should_lose_resource, child_resource_provider_->IsLost(resource));
2016 // Lost resources stay in use in the parent forever.
2017 EXPECT_EQ(should_lose_resource,
2018 child_resource_provider_->InUseByConsumer(resource));
2021 TEST_P(ResourceProviderTest, LostResourceInGrandParent) {
2022 gfx::Size size(1, 1);
2023 ResourceFormat format = RGBA_8888;
2024 ResourceProvider::ResourceId resource =
2025 child_resource_provider_->CreateResource(
2026 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE,
2027 format);
2028 child_resource_provider_->AllocateForTesting(resource);
2030 ReturnedResourceArray returned_to_child;
2031 int child_id =
2032 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
2034 // Transfer the resource to the parent.
2035 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2036 resource_ids_to_transfer.push_back(resource);
2037 TransferableResourceArray list;
2038 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
2039 &list);
2040 EXPECT_EQ(1u, list.size());
2042 resource_provider_->ReceiveFromChild(child_id, list);
2043 resource_provider_->DeclareUsedResourcesFromChild(child_id,
2044 resource_ids_to_transfer);
2048 ResourceProvider::ResourceIdMap resource_map =
2049 resource_provider_->GetChildToParentMap(child_id);
2050 ResourceProvider::ResourceId parent_resource = resource_map[resource];
2051 EXPECT_NE(0u, parent_resource);
2053 // Transfer to a grandparent.
2054 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2055 resource_ids_to_transfer.push_back(parent_resource);
2056 TransferableResourceArray list;
2057 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
2059 // Receive back a lost resource from the grandparent.
2060 EXPECT_EQ(1u, list.size());
2061 EXPECT_EQ(parent_resource, list[0].id);
2062 ReturnedResourceArray returned;
2063 TransferableResource::ReturnResources(list, &returned);
2064 EXPECT_EQ(1u, returned.size());
2065 EXPECT_EQ(parent_resource, returned[0].id);
2066 returned[0].lost = true;
2067 resource_provider_->ReceiveReturnsFromParent(returned);
2069 // The resource should be lost.
2070 EXPECT_TRUE(resource_provider_->IsLost(parent_resource));
2072 // Lost resources stay in use in the parent forever.
2073 EXPECT_TRUE(resource_provider_->InUseByConsumer(parent_resource));
2077 EXPECT_EQ(0u, returned_to_child.size());
2079 // Transfer resources back from the parent to the child. Set no resources as
2080 // being in use.
2081 ResourceProvider::ResourceIdArray no_resources;
2082 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
2084 // Expect the resource to be lost.
2085 ASSERT_EQ(1u, returned_to_child.size());
2086 EXPECT_TRUE(returned_to_child[0].lost);
2087 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
2088 returned_to_child.clear();
2091 // The resource should be lost.
2092 EXPECT_TRUE(child_resource_provider_->IsLost(resource));
2094 // Lost resources stay in use in the parent forever.
2095 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(resource));
2098 TEST_P(ResourceProviderTest, LostMailboxInParent) {
2099 uint32 release_sync_point = 0;
2100 bool lost_resource = false;
2101 bool release_called = false;
2102 uint32 sync_point = 0;
2103 ResourceProvider::ResourceId resource = CreateChildMailbox(
2104 &release_sync_point, &lost_resource, &release_called, &sync_point);
2106 ReturnedResourceArray returned_to_child;
2107 int child_id =
2108 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
2110 // Transfer the resource to the parent.
2111 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2112 resource_ids_to_transfer.push_back(resource);
2113 TransferableResourceArray list;
2114 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
2115 &list);
2116 EXPECT_EQ(1u, list.size());
2118 resource_provider_->ReceiveFromChild(child_id, list);
2119 resource_provider_->DeclareUsedResourcesFromChild(child_id,
2120 resource_ids_to_transfer);
2123 // Lose the output surface in the parent.
2124 resource_provider_->DidLoseOutputSurface();
2127 EXPECT_EQ(0u, returned_to_child.size());
2129 // Transfer resources back from the parent to the child. Set no resources as
2130 // being in use.
2131 ResourceProvider::ResourceIdArray no_resources;
2132 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
2134 ASSERT_EQ(1u, returned_to_child.size());
2135 // Losing an output surface only loses hardware resources.
2136 EXPECT_EQ(returned_to_child[0].lost,
2137 GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE);
2138 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
2139 returned_to_child.clear();
2142 // Delete the resource in the child. Expect the resource to be lost if it's
2143 // a GL texture.
2144 child_resource_provider_->DeleteResource(resource);
2145 EXPECT_EQ(lost_resource,
2146 GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE);
2149 TEST_P(ResourceProviderTest, LostMailboxInGrandParent) {
2150 uint32 release_sync_point = 0;
2151 bool lost_resource = false;
2152 bool release_called = false;
2153 uint32 sync_point = 0;
2154 ResourceProvider::ResourceId resource = CreateChildMailbox(
2155 &release_sync_point, &lost_resource, &release_called, &sync_point);
2157 ReturnedResourceArray returned_to_child;
2158 int child_id =
2159 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
2161 // Transfer the resource to the parent.
2162 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2163 resource_ids_to_transfer.push_back(resource);
2164 TransferableResourceArray list;
2165 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
2166 &list);
2167 EXPECT_EQ(1u, list.size());
2169 resource_provider_->ReceiveFromChild(child_id, list);
2170 resource_provider_->DeclareUsedResourcesFromChild(child_id,
2171 resource_ids_to_transfer);
2175 ResourceProvider::ResourceIdMap resource_map =
2176 resource_provider_->GetChildToParentMap(child_id);
2177 ResourceProvider::ResourceId parent_resource = resource_map[resource];
2178 EXPECT_NE(0u, parent_resource);
2180 // Transfer to a grandparent.
2181 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2182 resource_ids_to_transfer.push_back(parent_resource);
2183 TransferableResourceArray list;
2184 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
2186 // Receive back a lost resource from the grandparent.
2187 EXPECT_EQ(1u, list.size());
2188 EXPECT_EQ(parent_resource, list[0].id);
2189 ReturnedResourceArray returned;
2190 TransferableResource::ReturnResources(list, &returned);
2191 EXPECT_EQ(1u, returned.size());
2192 EXPECT_EQ(parent_resource, returned[0].id);
2193 returned[0].lost = true;
2194 resource_provider_->ReceiveReturnsFromParent(returned);
2198 EXPECT_EQ(0u, returned_to_child.size());
2200 // Transfer resources back from the parent to the child. Set no resources as
2201 // being in use.
2202 ResourceProvider::ResourceIdArray no_resources;
2203 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
2205 // Expect the resource to be lost.
2206 ASSERT_EQ(1u, returned_to_child.size());
2207 EXPECT_TRUE(returned_to_child[0].lost);
2208 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
2209 returned_to_child.clear();
2212 // Delete the resource in the child. Expect the resource to be lost.
2213 child_resource_provider_->DeleteResource(resource);
2214 EXPECT_TRUE(lost_resource);
2217 TEST_P(ResourceProviderTest, Shutdown) {
2218 uint32 release_sync_point = 0;
2219 bool lost_resource = false;
2220 bool release_called = false;
2221 uint32 sync_point = 0;
2222 CreateChildMailbox(
2223 &release_sync_point, &lost_resource, &release_called, &sync_point);
2225 EXPECT_EQ(0u, release_sync_point);
2226 EXPECT_FALSE(lost_resource);
2228 child_resource_provider_ = nullptr;
2230 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) {
2231 EXPECT_LE(sync_point, release_sync_point);
2233 EXPECT_TRUE(release_called);
2234 EXPECT_FALSE(lost_resource);
2237 TEST_P(ResourceProviderTest, ShutdownWithExportedResource) {
2238 uint32 release_sync_point = 0;
2239 bool lost_resource = false;
2240 bool release_called = false;
2241 uint32 sync_point = 0;
2242 ResourceProvider::ResourceId resource = CreateChildMailbox(
2243 &release_sync_point, &lost_resource, &release_called, &sync_point);
2245 // Transfer the resource, so we can't release it properly on shutdown.
2246 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2247 resource_ids_to_transfer.push_back(resource);
2248 TransferableResourceArray list;
2249 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
2250 &list);
2252 EXPECT_EQ(0u, release_sync_point);
2253 EXPECT_FALSE(lost_resource);
2255 child_resource_provider_ = nullptr;
2257 // Since the resource is in the parent, the child considers it lost.
2258 EXPECT_EQ(0u, release_sync_point);
2259 EXPECT_TRUE(lost_resource);
2262 TEST_P(ResourceProviderTest, LostContext) {
2263 // TextureMailbox callbacks only exist for GL textures for now.
2264 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
2265 return;
2266 unsigned texture = context()->createTexture();
2267 context()->bindTexture(GL_TEXTURE_2D, texture);
2268 gpu::Mailbox mailbox;
2269 context()->genMailboxCHROMIUM(mailbox.name);
2270 context()->produceTextureDirectCHROMIUM(texture, GL_TEXTURE_2D, mailbox.name);
2271 uint32 sync_point = context()->insertSyncPoint();
2273 EXPECT_LT(0u, sync_point);
2275 uint32 release_sync_point = 0;
2276 bool lost_resource = false;
2277 BlockingTaskRunner* main_thread_task_runner = NULL;
2278 scoped_ptr<SingleReleaseCallbackImpl> callback =
2279 SingleReleaseCallbackImpl::Create(base::Bind(ReleaseCallback,
2280 &release_sync_point,
2281 &lost_resource,
2282 &main_thread_task_runner));
2283 resource_provider_->CreateResourceFromTextureMailbox(
2284 TextureMailbox(mailbox, GL_TEXTURE_2D, sync_point), callback.Pass());
2286 EXPECT_EQ(0u, release_sync_point);
2287 EXPECT_FALSE(lost_resource);
2288 EXPECT_EQ(NULL, main_thread_task_runner);
2290 resource_provider_->DidLoseOutputSurface();
2291 resource_provider_ = nullptr;
2293 EXPECT_LE(sync_point, release_sync_point);
2294 EXPECT_TRUE(lost_resource);
2295 EXPECT_EQ(main_thread_task_runner_.get(), main_thread_task_runner);
2298 TEST_P(ResourceProviderTest, ScopedSampler) {
2299 // Sampling is only supported for GL textures.
2300 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
2301 return;
2303 scoped_ptr<TextureStateTrackingContext> context_owned(
2304 new TextureStateTrackingContext);
2305 TextureStateTrackingContext* context = context_owned.get();
2307 FakeOutputSurfaceClient output_surface_client;
2308 scoped_ptr<OutputSurface> output_surface(
2309 FakeOutputSurface::Create3d(context_owned.Pass()));
2310 CHECK(output_surface->BindToClient(&output_surface_client));
2312 scoped_ptr<ResourceProvider> resource_provider(
2313 ResourceProvider::Create(output_surface.get(),
2314 shared_bitmap_manager_.get(),
2315 gpu_memory_buffer_manager_.get(),
2316 NULL,
2318 false,
2319 1));
2321 gfx::Size size(1, 1);
2322 ResourceFormat format = RGBA_8888;
2323 int texture_id = 1;
2325 ResourceProvider::ResourceId id = resource_provider->CreateResource(
2326 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
2328 // Check that the texture gets created with the right sampler settings.
2329 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id))
2330 .Times(2); // Once to create and once to allocate.
2331 EXPECT_CALL(*context,
2332 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
2333 EXPECT_CALL(*context,
2334 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
2335 EXPECT_CALL(
2336 *context,
2337 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
2338 EXPECT_CALL(
2339 *context,
2340 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
2341 EXPECT_CALL(*context,
2342 texParameteri(GL_TEXTURE_2D,
2343 GL_TEXTURE_POOL_CHROMIUM,
2344 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM));
2346 resource_provider->AllocateForTesting(id);
2347 Mock::VerifyAndClearExpectations(context);
2349 // Creating a sampler with the default filter should not change any texture
2350 // parameters.
2352 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
2353 ResourceProvider::ScopedSamplerGL sampler(
2354 resource_provider.get(), id, GL_TEXTURE_2D, GL_LINEAR);
2355 Mock::VerifyAndClearExpectations(context);
2358 // Using a different filter should be reflected in the texture parameters.
2360 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
2361 EXPECT_CALL(
2362 *context,
2363 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
2364 EXPECT_CALL(
2365 *context,
2366 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
2367 ResourceProvider::ScopedSamplerGL sampler(
2368 resource_provider.get(), id, GL_TEXTURE_2D, GL_NEAREST);
2369 Mock::VerifyAndClearExpectations(context);
2372 // Test resetting to the default filter.
2374 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
2375 EXPECT_CALL(*context,
2376 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
2377 EXPECT_CALL(*context,
2378 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
2379 ResourceProvider::ScopedSamplerGL sampler(
2380 resource_provider.get(), id, GL_TEXTURE_2D, GL_LINEAR);
2381 Mock::VerifyAndClearExpectations(context);
2385 TEST_P(ResourceProviderTest, ManagedResource) {
2386 // Sampling is only supported for GL textures.
2387 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
2388 return;
2390 scoped_ptr<TextureStateTrackingContext> context_owned(
2391 new TextureStateTrackingContext);
2392 TextureStateTrackingContext* context = context_owned.get();
2394 FakeOutputSurfaceClient output_surface_client;
2395 scoped_ptr<OutputSurface> output_surface(
2396 FakeOutputSurface::Create3d(context_owned.Pass()));
2397 CHECK(output_surface->BindToClient(&output_surface_client));
2399 scoped_ptr<ResourceProvider> resource_provider(
2400 ResourceProvider::Create(output_surface.get(),
2401 shared_bitmap_manager_.get(),
2402 gpu_memory_buffer_manager_.get(),
2403 NULL,
2405 false,
2406 1));
2408 gfx::Size size(1, 1);
2409 ResourceFormat format = RGBA_8888;
2410 int texture_id = 1;
2412 // Check that the texture gets created with the right sampler settings.
2413 ResourceProvider::ResourceId id = resource_provider->CreateManagedResource(
2414 size, GL_TEXTURE_2D, GL_CLAMP_TO_EDGE,
2415 ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
2416 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
2417 EXPECT_CALL(*context,
2418 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
2419 EXPECT_CALL(*context,
2420 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
2421 EXPECT_CALL(
2422 *context,
2423 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
2424 EXPECT_CALL(
2425 *context,
2426 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
2427 EXPECT_CALL(*context,
2428 texParameteri(GL_TEXTURE_2D,
2429 GL_TEXTURE_POOL_CHROMIUM,
2430 GL_TEXTURE_POOL_MANAGED_CHROMIUM));
2431 resource_provider->CreateForTesting(id);
2432 EXPECT_NE(0u, id);
2434 Mock::VerifyAndClearExpectations(context);
2437 TEST_P(ResourceProviderTest, TextureWrapMode) {
2438 // Sampling is only supported for GL textures.
2439 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
2440 return;
2442 scoped_ptr<TextureStateTrackingContext> context_owned(
2443 new TextureStateTrackingContext);
2444 TextureStateTrackingContext* context = context_owned.get();
2446 FakeOutputSurfaceClient output_surface_client;
2447 scoped_ptr<OutputSurface> output_surface(
2448 FakeOutputSurface::Create3d(context_owned.Pass()));
2449 CHECK(output_surface->BindToClient(&output_surface_client));
2451 scoped_ptr<ResourceProvider> resource_provider(
2452 ResourceProvider::Create(output_surface.get(),
2453 shared_bitmap_manager_.get(),
2454 gpu_memory_buffer_manager_.get(),
2455 NULL,
2457 false,
2458 1));
2460 gfx::Size size(1, 1);
2461 ResourceFormat format = RGBA_8888;
2462 GLenum texture_pool = GL_TEXTURE_POOL_UNMANAGED_CHROMIUM;
2464 for (int texture_id = 1; texture_id <= 2; ++texture_id) {
2465 GLint wrap_mode = texture_id == 1 ? GL_CLAMP_TO_EDGE : GL_REPEAT;
2466 // Check that the texture gets created with the right sampler settings.
2467 ResourceProvider::ResourceId id = resource_provider->CreateGLTexture(
2468 size, GL_TEXTURE_2D, texture_pool, wrap_mode,
2469 ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
2470 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
2471 EXPECT_CALL(*context,
2472 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
2473 EXPECT_CALL(*context,
2474 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
2475 EXPECT_CALL(*context,
2476 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap_mode));
2477 EXPECT_CALL(*context,
2478 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap_mode));
2479 EXPECT_CALL(*context,
2480 texParameteri(GL_TEXTURE_2D,
2481 GL_TEXTURE_POOL_CHROMIUM,
2482 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM));
2483 resource_provider->CreateForTesting(id);
2484 EXPECT_NE(0u, id);
2486 Mock::VerifyAndClearExpectations(context);
2490 TEST_P(ResourceProviderTest, TextureHint) {
2491 // Sampling is only supported for GL textures.
2492 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
2493 return;
2495 scoped_ptr<TextureStateTrackingContext> context_owned(
2496 new TextureStateTrackingContext);
2497 TextureStateTrackingContext* context = context_owned.get();
2498 context->set_support_texture_storage(true);
2499 context->set_support_texture_usage(true);
2501 FakeOutputSurfaceClient output_surface_client;
2502 scoped_ptr<OutputSurface> output_surface(
2503 FakeOutputSurface::Create3d(context_owned.Pass()));
2504 CHECK(output_surface->BindToClient(&output_surface_client));
2506 scoped_ptr<ResourceProvider> resource_provider(
2507 ResourceProvider::Create(output_surface.get(),
2508 shared_bitmap_manager_.get(),
2509 gpu_memory_buffer_manager_.get(),
2510 NULL,
2512 false,
2513 1));
2515 gfx::Size size(1, 1);
2516 ResourceFormat format = RGBA_8888;
2517 GLenum texture_pool = GL_TEXTURE_POOL_UNMANAGED_CHROMIUM;
2519 const ResourceProvider::TextureHint hints[4] = {
2520 ResourceProvider::TEXTURE_HINT_DEFAULT,
2521 ResourceProvider::TEXTURE_HINT_IMMUTABLE,
2522 ResourceProvider::TEXTURE_HINT_FRAMEBUFFER,
2523 ResourceProvider::TEXTURE_HINT_IMMUTABLE_FRAMEBUFFER,
2525 for (GLuint texture_id = 1; texture_id <= arraysize(hints); ++texture_id) {
2526 // Check that the texture gets created with the right sampler settings.
2527 ResourceProvider::ResourceId id =
2528 resource_provider->CreateGLTexture(size,
2529 GL_TEXTURE_2D,
2530 texture_pool,
2531 GL_CLAMP_TO_EDGE,
2532 hints[texture_id - 1],
2533 format);
2534 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
2535 EXPECT_CALL(*context,
2536 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
2537 EXPECT_CALL(*context,
2538 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
2539 EXPECT_CALL(
2540 *context,
2541 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
2542 EXPECT_CALL(
2543 *context,
2544 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
2545 EXPECT_CALL(*context,
2546 texParameteri(GL_TEXTURE_2D,
2547 GL_TEXTURE_POOL_CHROMIUM,
2548 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM));
2549 // Check only TEXTURE_HINT_FRAMEBUFFER set GL_TEXTURE_USAGE_ANGLE.
2550 bool is_framebuffer_hint =
2551 hints[texture_id - 1] & ResourceProvider::TEXTURE_HINT_FRAMEBUFFER;
2552 EXPECT_CALL(*context,
2553 texParameteri(GL_TEXTURE_2D,
2554 GL_TEXTURE_USAGE_ANGLE,
2555 GL_FRAMEBUFFER_ATTACHMENT_ANGLE))
2556 .Times(is_framebuffer_hint ? 1 : 0);
2557 resource_provider->CreateForTesting(id);
2558 EXPECT_NE(0u, id);
2560 Mock::VerifyAndClearExpectations(context);
2564 TEST_P(ResourceProviderTest, TextureMailbox_SharedMemory) {
2565 if (GetParam() != ResourceProvider::RESOURCE_TYPE_BITMAP)
2566 return;
2568 gfx::Size size(64, 64);
2569 const uint32_t kBadBeef = 0xbadbeef;
2570 scoped_ptr<SharedBitmap> shared_bitmap(
2571 CreateAndFillSharedBitmap(shared_bitmap_manager_.get(), size, kBadBeef));
2573 FakeOutputSurfaceClient output_surface_client;
2574 scoped_ptr<OutputSurface> output_surface(
2575 FakeOutputSurface::CreateSoftware(make_scoped_ptr(
2576 new SoftwareOutputDevice)));
2577 CHECK(output_surface->BindToClient(&output_surface_client));
2579 scoped_ptr<ResourceProvider> resource_provider(
2580 ResourceProvider::Create(output_surface.get(),
2581 shared_bitmap_manager_.get(),
2582 gpu_memory_buffer_manager_.get(),
2583 main_thread_task_runner_.get(),
2585 false,
2586 1));
2588 uint32 release_sync_point = 0;
2589 bool lost_resource = false;
2590 BlockingTaskRunner* main_thread_task_runner = NULL;
2591 scoped_ptr<SingleReleaseCallbackImpl> callback =
2592 SingleReleaseCallbackImpl::Create(base::Bind(&ReleaseCallback,
2593 &release_sync_point,
2594 &lost_resource,
2595 &main_thread_task_runner));
2596 TextureMailbox mailbox(shared_bitmap.get(), size);
2598 ResourceProvider::ResourceId id =
2599 resource_provider->CreateResourceFromTextureMailbox(
2600 mailbox, callback.Pass());
2601 EXPECT_NE(0u, id);
2604 ResourceProvider::ScopedReadLockSoftware lock(resource_provider.get(), id);
2605 const SkBitmap* sk_bitmap = lock.sk_bitmap();
2606 EXPECT_EQ(sk_bitmap->width(), size.width());
2607 EXPECT_EQ(sk_bitmap->height(), size.height());
2608 EXPECT_EQ(*sk_bitmap->getAddr32(16, 16), kBadBeef);
2611 resource_provider->DeleteResource(id);
2612 EXPECT_EQ(0u, release_sync_point);
2613 EXPECT_FALSE(lost_resource);
2614 EXPECT_EQ(main_thread_task_runner_.get(), main_thread_task_runner);
2617 class ResourceProviderTestTextureMailboxGLFilters
2618 : public ResourceProviderTest {
2619 public:
2620 static void RunTest(TestSharedBitmapManager* shared_bitmap_manager,
2621 TestGpuMemoryBufferManager* gpu_memory_buffer_manager,
2622 BlockingTaskRunner* main_thread_task_runner,
2623 bool mailbox_nearest_neighbor,
2624 GLenum sampler_filter) {
2625 scoped_ptr<TextureStateTrackingContext> context_owned(
2626 new TextureStateTrackingContext);
2627 TextureStateTrackingContext* context = context_owned.get();
2629 FakeOutputSurfaceClient output_surface_client;
2630 scoped_ptr<OutputSurface> output_surface(
2631 FakeOutputSurface::Create3d(context_owned.Pass()));
2632 CHECK(output_surface->BindToClient(&output_surface_client));
2634 scoped_ptr<ResourceProvider> resource_provider(
2635 ResourceProvider::Create(output_surface.get(),
2636 shared_bitmap_manager,
2637 gpu_memory_buffer_manager,
2638 main_thread_task_runner,
2640 false,
2641 1));
2643 unsigned texture_id = 1;
2644 uint32 sync_point = 30;
2645 unsigned target = GL_TEXTURE_2D;
2647 EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
2648 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
2649 EXPECT_CALL(*context, insertSyncPoint()).Times(0);
2650 EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _, _)).Times(0);
2651 EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(_, _)).Times(0);
2653 gpu::Mailbox gpu_mailbox;
2654 memcpy(gpu_mailbox.name, "Hello world", strlen("Hello world") + 1);
2655 uint32 release_sync_point = 0;
2656 bool lost_resource = false;
2657 BlockingTaskRunner* mailbox_task_runner = NULL;
2658 scoped_ptr<SingleReleaseCallbackImpl> callback =
2659 SingleReleaseCallbackImpl::Create(base::Bind(&ReleaseCallback,
2660 &release_sync_point,
2661 &lost_resource,
2662 &mailbox_task_runner));
2664 TextureMailbox mailbox(gpu_mailbox, target, sync_point);
2665 mailbox.set_nearest_neighbor(mailbox_nearest_neighbor);
2667 ResourceProvider::ResourceId id =
2668 resource_provider->CreateResourceFromTextureMailbox(mailbox,
2669 callback.Pass());
2670 EXPECT_NE(0u, id);
2672 Mock::VerifyAndClearExpectations(context);
2675 // Mailbox sync point WaitSyncPoint before using the texture.
2676 EXPECT_CALL(*context, waitSyncPoint(sync_point));
2677 resource_provider->WaitSyncPointIfNeeded(id);
2678 Mock::VerifyAndClearExpectations(context);
2680 EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(target, _))
2681 .WillOnce(Return(texture_id));
2682 EXPECT_CALL(*context, bindTexture(target, texture_id));
2684 EXPECT_CALL(*context, insertSyncPoint()).Times(0);
2685 EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _, _)).Times(0);
2687 // The sampler will reset these if |mailbox_nearest_neighbor| does not
2688 // match |sampler_filter|.
2689 if (mailbox_nearest_neighbor != (sampler_filter == GL_NEAREST)) {
2690 EXPECT_CALL(*context, texParameteri(
2691 GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, sampler_filter));
2692 EXPECT_CALL(*context, texParameteri(
2693 GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, sampler_filter));
2696 ResourceProvider::ScopedSamplerGL lock(
2697 resource_provider.get(), id, sampler_filter);
2698 Mock::VerifyAndClearExpectations(context);
2700 // When done with it, a sync point should be inserted, but no produce is
2701 // necessary.
2702 EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
2703 EXPECT_CALL(*context, insertSyncPoint());
2704 EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _, _)).Times(0);
2706 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
2707 EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(_, _)).Times(0);
2710 resource_provider->DeleteResource(id);
2711 EXPECT_EQ(0u, release_sync_point);
2712 EXPECT_FALSE(lost_resource);
2713 EXPECT_EQ(main_thread_task_runner, mailbox_task_runner);
2717 TEST_P(ResourceProviderTest, TextureMailbox_GLTexture2D_LinearToLinear) {
2718 // Mailboxing is only supported for GL textures.
2719 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
2720 return;
2722 ResourceProviderTestTextureMailboxGLFilters::RunTest(
2723 shared_bitmap_manager_.get(),
2724 gpu_memory_buffer_manager_.get(),
2725 main_thread_task_runner_.get(),
2726 false,
2727 GL_LINEAR);
2730 TEST_P(ResourceProviderTest, TextureMailbox_GLTexture2D_NearestToNearest) {
2731 // Mailboxing is only supported for GL textures.
2732 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
2733 return;
2735 ResourceProviderTestTextureMailboxGLFilters::RunTest(
2736 shared_bitmap_manager_.get(),
2737 gpu_memory_buffer_manager_.get(),
2738 main_thread_task_runner_.get(),
2739 true,
2740 GL_NEAREST);
2743 TEST_P(ResourceProviderTest, TextureMailbox_GLTexture2D_NearestToLinear) {
2744 // Mailboxing is only supported for GL textures.
2745 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
2746 return;
2748 ResourceProviderTestTextureMailboxGLFilters::RunTest(
2749 shared_bitmap_manager_.get(),
2750 gpu_memory_buffer_manager_.get(),
2751 main_thread_task_runner_.get(),
2752 true,
2753 GL_LINEAR);
2756 TEST_P(ResourceProviderTest, TextureMailbox_GLTexture2D_LinearToNearest) {
2757 // Mailboxing is only supported for GL textures.
2758 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
2759 return;
2761 ResourceProviderTestTextureMailboxGLFilters::RunTest(
2762 shared_bitmap_manager_.get(),
2763 gpu_memory_buffer_manager_.get(),
2764 main_thread_task_runner_.get(),
2765 false,
2766 GL_NEAREST);
2769 TEST_P(ResourceProviderTest, TextureMailbox_GLTextureExternalOES) {
2770 // Mailboxing is only supported for GL textures.
2771 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
2772 return;
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_.get(),
2786 gpu_memory_buffer_manager_.get(),
2787 NULL,
2789 false,
2790 1));
2792 uint32 sync_point = 30;
2793 unsigned target = GL_TEXTURE_EXTERNAL_OES;
2795 EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
2796 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
2797 EXPECT_CALL(*context, insertSyncPoint()).Times(0);
2798 EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _, _)).Times(0);
2799 EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(_, _)).Times(0);
2801 gpu::Mailbox gpu_mailbox;
2802 memcpy(gpu_mailbox.name, "Hello world", strlen("Hello world") + 1);
2803 scoped_ptr<SingleReleaseCallbackImpl> callback =
2804 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback));
2806 TextureMailbox mailbox(gpu_mailbox, target, sync_point);
2808 ResourceProvider::ResourceId id =
2809 resource_provider->CreateResourceFromTextureMailbox(
2810 mailbox, callback.Pass());
2811 EXPECT_NE(0u, id);
2813 Mock::VerifyAndClearExpectations(context);
2816 // Mailbox sync point WaitSyncPoint before using the texture.
2817 EXPECT_CALL(*context, waitSyncPoint(sync_point));
2818 resource_provider->WaitSyncPointIfNeeded(id);
2819 Mock::VerifyAndClearExpectations(context);
2821 unsigned texture_id = 1;
2823 EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(target, _))
2824 .WillOnce(Return(texture_id));
2826 EXPECT_CALL(*context, insertSyncPoint()).Times(0);
2827 EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _, _)).Times(0);
2829 ResourceProvider::ScopedReadLockGL lock(resource_provider.get(), id);
2830 Mock::VerifyAndClearExpectations(context);
2832 // When done with it, a sync point should be inserted, but no produce is
2833 // necessary.
2834 EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
2835 EXPECT_CALL(*context, insertSyncPoint());
2836 EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _, _)).Times(0);
2838 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
2839 EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(_, _)).Times(0);
2843 TEST_P(ResourceProviderTest,
2844 TextureMailbox_WaitSyncPointIfNeeded_WithSyncPoint) {
2845 // Mailboxing is only supported for GL textures.
2846 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
2847 return;
2849 scoped_ptr<TextureStateTrackingContext> context_owned(
2850 new TextureStateTrackingContext);
2851 TextureStateTrackingContext* context = context_owned.get();
2853 FakeOutputSurfaceClient output_surface_client;
2854 scoped_ptr<OutputSurface> output_surface(
2855 FakeOutputSurface::Create3d(context_owned.Pass()));
2856 CHECK(output_surface->BindToClient(&output_surface_client));
2858 scoped_ptr<ResourceProvider> resource_provider(
2859 ResourceProvider::Create(output_surface.get(),
2860 shared_bitmap_manager_.get(),
2861 gpu_memory_buffer_manager_.get(),
2862 NULL,
2864 false,
2865 1));
2867 uint32 sync_point = 30;
2868 unsigned target = GL_TEXTURE_2D;
2870 EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
2871 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
2872 EXPECT_CALL(*context, insertSyncPoint()).Times(0);
2873 EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _, _)).Times(0);
2874 EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(_, _)).Times(0);
2876 gpu::Mailbox gpu_mailbox;
2877 memcpy(gpu_mailbox.name, "Hello world", strlen("Hello world") + 1);
2878 scoped_ptr<SingleReleaseCallbackImpl> callback =
2879 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback));
2881 TextureMailbox mailbox(gpu_mailbox, target, sync_point);
2883 ResourceProvider::ResourceId id =
2884 resource_provider->CreateResourceFromTextureMailbox(mailbox,
2885 callback.Pass());
2886 EXPECT_NE(0u, id);
2888 Mock::VerifyAndClearExpectations(context);
2891 // First call to WaitSyncPointIfNeeded should call waitSyncPoint.
2892 EXPECT_CALL(*context, waitSyncPoint(sync_point));
2893 resource_provider->WaitSyncPointIfNeeded(id);
2894 Mock::VerifyAndClearExpectations(context);
2896 // Subsequent calls to WaitSyncPointIfNeeded shouldn't call waitSyncPoint.
2897 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
2898 resource_provider->WaitSyncPointIfNeeded(id);
2899 Mock::VerifyAndClearExpectations(context);
2903 TEST_P(ResourceProviderTest, TextureMailbox_WaitSyncPointIfNeeded_NoSyncPoint) {
2904 // Mailboxing is only supported for GL textures.
2905 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
2906 return;
2908 scoped_ptr<TextureStateTrackingContext> context_owned(
2909 new TextureStateTrackingContext);
2910 TextureStateTrackingContext* context = context_owned.get();
2912 FakeOutputSurfaceClient output_surface_client;
2913 scoped_ptr<OutputSurface> output_surface(
2914 FakeOutputSurface::Create3d(context_owned.Pass()));
2915 CHECK(output_surface->BindToClient(&output_surface_client));
2917 scoped_ptr<ResourceProvider> resource_provider(
2918 ResourceProvider::Create(output_surface.get(),
2919 shared_bitmap_manager_.get(),
2920 gpu_memory_buffer_manager_.get(),
2921 NULL,
2923 false,
2924 1));
2926 uint32 sync_point = 0;
2927 unsigned target = GL_TEXTURE_2D;
2929 EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
2930 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
2931 EXPECT_CALL(*context, insertSyncPoint()).Times(0);
2932 EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _, _)).Times(0);
2933 EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(_, _)).Times(0);
2935 gpu::Mailbox gpu_mailbox;
2936 memcpy(gpu_mailbox.name, "Hello world", strlen("Hello world") + 1);
2937 scoped_ptr<SingleReleaseCallbackImpl> callback =
2938 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback));
2940 TextureMailbox mailbox(gpu_mailbox, target, sync_point);
2942 ResourceProvider::ResourceId id =
2943 resource_provider->CreateResourceFromTextureMailbox(mailbox,
2944 callback.Pass());
2945 EXPECT_NE(0u, id);
2947 Mock::VerifyAndClearExpectations(context);
2950 // WaitSyncPointIfNeeded with sync_point == 0 shouldn't call waitSyncPoint.
2951 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
2952 resource_provider->WaitSyncPointIfNeeded(id);
2953 Mock::VerifyAndClearExpectations(context);
2957 class AllocationTrackingContext3D : public TestWebGraphicsContext3D {
2958 public:
2959 MOCK_METHOD0(NextTextureId, GLuint());
2960 MOCK_METHOD1(RetireTextureId, void(GLuint id));
2961 MOCK_METHOD2(bindTexture, void(GLenum target, GLuint texture));
2962 MOCK_METHOD5(texStorage2DEXT,
2963 void(GLenum target,
2964 GLint levels,
2965 GLuint internalformat,
2966 GLint width,
2967 GLint height));
2968 MOCK_METHOD9(texImage2D,
2969 void(GLenum target,
2970 GLint level,
2971 GLenum internalformat,
2972 GLsizei width,
2973 GLsizei height,
2974 GLint border,
2975 GLenum format,
2976 GLenum type,
2977 const void* pixels));
2978 MOCK_METHOD9(texSubImage2D,
2979 void(GLenum target,
2980 GLint level,
2981 GLint xoffset,
2982 GLint yoffset,
2983 GLsizei width,
2984 GLsizei height,
2985 GLenum format,
2986 GLenum type,
2987 const void* pixels));
2988 MOCK_METHOD9(asyncTexImage2DCHROMIUM,
2989 void(GLenum target,
2990 GLint level,
2991 GLenum internalformat,
2992 GLsizei width,
2993 GLsizei height,
2994 GLint border,
2995 GLenum format,
2996 GLenum type,
2997 const void* pixels));
2998 MOCK_METHOD9(asyncTexSubImage2DCHROMIUM,
2999 void(GLenum target,
3000 GLint level,
3001 GLint xoffset,
3002 GLint yoffset,
3003 GLsizei width,
3004 GLsizei height,
3005 GLenum format,
3006 GLenum type,
3007 const void* pixels));
3008 MOCK_METHOD8(compressedTexImage2D,
3009 void(GLenum target,
3010 GLint level,
3011 GLenum internalformat,
3012 GLsizei width,
3013 GLsizei height,
3014 GLint border,
3015 GLsizei image_size,
3016 const void* data));
3017 MOCK_METHOD1(waitAsyncTexImage2DCHROMIUM, void(GLenum));
3018 MOCK_METHOD4(createImageCHROMIUM,
3019 GLuint(ClientBuffer, GLsizei, GLsizei, GLenum));
3020 MOCK_METHOD1(destroyImageCHROMIUM, void(GLuint));
3021 MOCK_METHOD2(bindTexImage2DCHROMIUM, void(GLenum, GLint));
3022 MOCK_METHOD2(releaseTexImage2DCHROMIUM, void(GLenum, GLint));
3024 // We're mocking bindTexture, so we override
3025 // TestWebGraphicsContext3D::texParameteri to avoid assertions related to the
3026 // currently bound texture.
3027 virtual void texParameteri(GLenum target, GLenum pname, GLint param) {}
3030 TEST_P(ResourceProviderTest, TextureAllocation) {
3031 // Only for GL textures.
3032 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
3033 return;
3034 scoped_ptr<AllocationTrackingContext3D> context_owned(
3035 new StrictMock<AllocationTrackingContext3D>);
3036 AllocationTrackingContext3D* context = context_owned.get();
3038 FakeOutputSurfaceClient output_surface_client;
3039 scoped_ptr<OutputSurface> output_surface(
3040 FakeOutputSurface::Create3d(context_owned.Pass()));
3041 CHECK(output_surface->BindToClient(&output_surface_client));
3043 scoped_ptr<ResourceProvider> resource_provider(
3044 ResourceProvider::Create(output_surface.get(),
3045 shared_bitmap_manager_.get(),
3046 gpu_memory_buffer_manager_.get(),
3047 NULL,
3049 false,
3050 1));
3052 gfx::Size size(2, 2);
3053 gfx::Vector2d offset(0, 0);
3054 ResourceFormat format = RGBA_8888;
3055 ResourceProvider::ResourceId id = 0;
3056 uint8_t pixels[16] = { 0 };
3057 int texture_id = 123;
3059 // Lazy allocation. Don't allocate when creating the resource.
3060 id = resource_provider->CreateResource(
3061 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
3063 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3064 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(1);
3065 resource_provider->CreateForTesting(id);
3067 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3068 resource_provider->DeleteResource(id);
3070 Mock::VerifyAndClearExpectations(context);
3072 // Do allocate when we set the pixels.
3073 id = resource_provider->CreateResource(
3074 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
3076 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3077 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(3);
3078 EXPECT_CALL(*context, texImage2D(_, _, _, 2, 2, _, _, _, _)).Times(1);
3079 EXPECT_CALL(*context, texSubImage2D(_, _, _, _, 2, 2, _, _, _)).Times(1);
3080 resource_provider->CopyToResource(id, pixels, size);
3082 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3083 resource_provider->DeleteResource(id);
3085 Mock::VerifyAndClearExpectations(context);
3087 // Same for async version.
3088 id = resource_provider->CreateResource(
3089 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
3090 resource_provider->AcquirePixelBuffer(id);
3092 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3093 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
3094 EXPECT_CALL(*context, asyncTexImage2DCHROMIUM(_, _, _, 2, 2, _, _, _, _))
3095 .Times(1);
3096 resource_provider->BeginSetPixels(id);
3097 ASSERT_TRUE(resource_provider->DidSetPixelsComplete(id));
3099 resource_provider->ReleasePixelBuffer(id);
3101 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3102 resource_provider->DeleteResource(id);
3104 Mock::VerifyAndClearExpectations(context);
3107 TEST_P(ResourceProviderTest, TextureAllocationHint) {
3108 // Only for GL textures.
3109 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
3110 return;
3111 scoped_ptr<AllocationTrackingContext3D> context_owned(
3112 new StrictMock<AllocationTrackingContext3D>);
3113 AllocationTrackingContext3D* context = context_owned.get();
3114 context->set_support_texture_storage(true);
3115 context->set_support_texture_usage(true);
3117 FakeOutputSurfaceClient output_surface_client;
3118 scoped_ptr<OutputSurface> output_surface(
3119 FakeOutputSurface::Create3d(context_owned.Pass()));
3120 CHECK(output_surface->BindToClient(&output_surface_client));
3122 scoped_ptr<ResourceProvider> resource_provider(
3123 ResourceProvider::Create(output_surface.get(),
3124 shared_bitmap_manager_.get(),
3125 gpu_memory_buffer_manager_.get(),
3126 NULL,
3128 false,
3129 1));
3131 gfx::Size size(2, 2);
3133 const ResourceFormat formats[2] = {RGBA_8888, BGRA_8888};
3134 const ResourceProvider::TextureHint hints[4] = {
3135 ResourceProvider::TEXTURE_HINT_DEFAULT,
3136 ResourceProvider::TEXTURE_HINT_IMMUTABLE,
3137 ResourceProvider::TEXTURE_HINT_FRAMEBUFFER,
3138 ResourceProvider::TEXTURE_HINT_IMMUTABLE_FRAMEBUFFER,
3140 for (size_t i = 0; i < arraysize(formats); ++i) {
3141 for (GLuint texture_id = 1; texture_id <= arraysize(hints); ++texture_id) {
3142 // Lazy allocation. Don't allocate when creating the resource.
3143 ResourceProvider::ResourceId id = resource_provider->CreateResource(
3144 size, GL_CLAMP_TO_EDGE, hints[texture_id - 1], formats[i]);
3146 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3147 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
3148 bool is_immutable_hint =
3149 hints[texture_id - 1] & ResourceProvider::TEXTURE_HINT_IMMUTABLE;
3150 bool support_immutable_texture =
3151 is_immutable_hint && formats[i] == RGBA_8888;
3152 EXPECT_CALL(*context, texStorage2DEXT(_, _, _, 2, 2))
3153 .Times(support_immutable_texture ? 1 : 0);
3154 EXPECT_CALL(*context, texImage2D(_, _, _, 2, 2, _, _, _, _))
3155 .Times(support_immutable_texture ? 0 : 1);
3156 resource_provider->AllocateForTesting(id);
3158 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3159 resource_provider->DeleteResource(id);
3161 Mock::VerifyAndClearExpectations(context);
3166 TEST_P(ResourceProviderTest, TextureAllocationHint_BGRA) {
3167 // Only for GL textures.
3168 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
3169 return;
3170 scoped_ptr<AllocationTrackingContext3D> context_owned(
3171 new StrictMock<AllocationTrackingContext3D>);
3172 AllocationTrackingContext3D* context = context_owned.get();
3173 context->set_support_texture_format_bgra8888(true);
3174 context->set_support_texture_storage(true);
3175 context->set_support_texture_usage(true);
3177 FakeOutputSurfaceClient output_surface_client;
3178 scoped_ptr<OutputSurface> output_surface(
3179 FakeOutputSurface::Create3d(context_owned.Pass()));
3180 CHECK(output_surface->BindToClient(&output_surface_client));
3182 scoped_ptr<ResourceProvider> resource_provider(
3183 ResourceProvider::Create(output_surface.get(),
3184 shared_bitmap_manager_.get(),
3185 gpu_memory_buffer_manager_.get(),
3186 NULL,
3188 false,
3189 1));
3191 gfx::Size size(2, 2);
3192 const ResourceFormat formats[2] = {RGBA_8888, BGRA_8888};
3194 const ResourceProvider::TextureHint hints[4] = {
3195 ResourceProvider::TEXTURE_HINT_DEFAULT,
3196 ResourceProvider::TEXTURE_HINT_IMMUTABLE,
3197 ResourceProvider::TEXTURE_HINT_FRAMEBUFFER,
3198 ResourceProvider::TEXTURE_HINT_IMMUTABLE_FRAMEBUFFER,
3200 for (size_t i = 0; i < arraysize(formats); ++i) {
3201 for (GLuint texture_id = 1; texture_id <= arraysize(hints); ++texture_id) {
3202 // Lazy allocation. Don't allocate when creating the resource.
3203 ResourceProvider::ResourceId id = resource_provider->CreateResource(
3204 size, GL_CLAMP_TO_EDGE, hints[texture_id - 1], formats[i]);
3206 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3207 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
3208 bool is_immutable_hint =
3209 hints[texture_id - 1] & ResourceProvider::TEXTURE_HINT_IMMUTABLE;
3210 EXPECT_CALL(*context, texStorage2DEXT(_, _, _, 2, 2))
3211 .Times(is_immutable_hint ? 1 : 0);
3212 EXPECT_CALL(*context, texImage2D(_, _, _, 2, 2, _, _, _, _))
3213 .Times(is_immutable_hint ? 0 : 1);
3214 resource_provider->AllocateForTesting(id);
3216 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3217 resource_provider->DeleteResource(id);
3219 Mock::VerifyAndClearExpectations(context);
3224 TEST_P(ResourceProviderTest, PixelBuffer_GLTexture) {
3225 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
3226 return;
3227 scoped_ptr<AllocationTrackingContext3D> context_owned(
3228 new StrictMock<AllocationTrackingContext3D>);
3229 AllocationTrackingContext3D* context = context_owned.get();
3231 FakeOutputSurfaceClient output_surface_client;
3232 scoped_ptr<OutputSurface> output_surface(
3233 FakeOutputSurface::Create3d(context_owned.Pass()));
3234 CHECK(output_surface->BindToClient(&output_surface_client));
3236 gfx::Size size(2, 2);
3237 ResourceFormat format = RGBA_8888;
3238 ResourceProvider::ResourceId id = 0;
3239 int texture_id = 123;
3241 scoped_ptr<ResourceProvider> resource_provider(
3242 ResourceProvider::Create(output_surface.get(),
3243 shared_bitmap_manager_.get(),
3244 gpu_memory_buffer_manager_.get(),
3245 NULL,
3247 false,
3248 1));
3250 id = resource_provider->CreateResource(
3251 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
3252 resource_provider->AcquirePixelBuffer(id);
3254 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3255 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
3256 EXPECT_CALL(*context, asyncTexImage2DCHROMIUM(_, _, _, 2, 2, _, _, _, _))
3257 .Times(1);
3258 resource_provider->BeginSetPixels(id);
3260 EXPECT_TRUE(resource_provider->DidSetPixelsComplete(id));
3262 resource_provider->ReleasePixelBuffer(id);
3264 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3265 resource_provider->DeleteResource(id);
3267 Mock::VerifyAndClearExpectations(context);
3270 TEST_P(ResourceProviderTest, ForcingAsyncUploadToComplete) {
3271 // Only for GL textures.
3272 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
3273 return;
3274 scoped_ptr<AllocationTrackingContext3D> context_owned(
3275 new StrictMock<AllocationTrackingContext3D>);
3276 AllocationTrackingContext3D* context = context_owned.get();
3278 FakeOutputSurfaceClient output_surface_client;
3279 scoped_ptr<OutputSurface> output_surface(
3280 FakeOutputSurface::Create3d(context_owned.Pass()));
3281 CHECK(output_surface->BindToClient(&output_surface_client));
3283 gfx::Size size(2, 2);
3284 ResourceFormat format = RGBA_8888;
3285 ResourceProvider::ResourceId id = 0;
3286 int texture_id = 123;
3288 scoped_ptr<ResourceProvider> resource_provider(
3289 ResourceProvider::Create(output_surface.get(),
3290 shared_bitmap_manager_.get(),
3291 gpu_memory_buffer_manager_.get(),
3292 NULL,
3294 false,
3295 1));
3297 id = resource_provider->CreateResource(
3298 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
3299 resource_provider->AcquirePixelBuffer(id);
3301 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3302 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
3303 EXPECT_CALL(*context, asyncTexImage2DCHROMIUM(_, _, _, 2, 2, _, _, _, _))
3304 .Times(1);
3305 resource_provider->BeginSetPixels(id);
3307 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(1);
3308 EXPECT_CALL(*context, waitAsyncTexImage2DCHROMIUM(GL_TEXTURE_2D)).Times(1);
3309 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, 0)).Times(1);
3310 resource_provider->ForceSetPixelsToComplete(id);
3312 resource_provider->ReleasePixelBuffer(id);
3314 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3315 resource_provider->DeleteResource(id);
3317 Mock::VerifyAndClearExpectations(context);
3320 TEST_P(ResourceProviderTest, PixelBufferLostContext) {
3321 scoped_ptr<AllocationTrackingContext3D> context_owned(
3322 new NiceMock<AllocationTrackingContext3D>);
3323 AllocationTrackingContext3D* context = context_owned.get();
3325 FakeOutputSurfaceClient output_surface_client;
3326 scoped_ptr<OutputSurface> output_surface(
3327 FakeOutputSurface::Create3d(context_owned.Pass()));
3328 CHECK(output_surface->BindToClient(&output_surface_client));
3330 gfx::Size size(2, 2);
3331 ResourceFormat format = RGBA_8888;
3332 ResourceProvider::ResourceId id = 0;
3333 int texture_id = 123;
3335 scoped_ptr<ResourceProvider> resource_provider(
3336 ResourceProvider::Create(output_surface.get(),
3337 shared_bitmap_manager_.get(),
3338 gpu_memory_buffer_manager_.get(),
3339 NULL,
3341 false,
3342 1));
3344 EXPECT_CALL(*context, NextTextureId()).WillRepeatedly(Return(texture_id));
3346 id = resource_provider->CreateResource(
3347 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
3348 context->loseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB,
3349 GL_INNOCENT_CONTEXT_RESET_ARB);
3351 resource_provider->AcquirePixelBuffer(id);
3352 int stride;
3353 void* buffer = resource_provider->MapPixelBuffer(id, &stride);
3354 EXPECT_FALSE(buffer);
3355 resource_provider->UnmapPixelBuffer(id);
3356 Mock::VerifyAndClearExpectations(context);
3359 TEST_P(ResourceProviderTest, Image_GLTexture) {
3360 // Only for GL textures.
3361 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
3362 return;
3363 scoped_ptr<AllocationTrackingContext3D> context_owned(
3364 new StrictMock<AllocationTrackingContext3D>);
3365 AllocationTrackingContext3D* context = context_owned.get();
3367 FakeOutputSurfaceClient output_surface_client;
3368 scoped_ptr<OutputSurface> output_surface(
3369 FakeOutputSurface::Create3d(context_owned.Pass()));
3370 CHECK(output_surface->BindToClient(&output_surface_client));
3372 const int kWidth = 2;
3373 const int kHeight = 2;
3374 gfx::Size size(kWidth, kHeight);
3375 ResourceFormat format = RGBA_8888;
3376 ResourceProvider::ResourceId id = 0;
3377 const unsigned kTextureId = 123u;
3378 const unsigned kImageId = 234u;
3380 scoped_ptr<ResourceProvider> resource_provider(
3381 ResourceProvider::Create(output_surface.get(),
3382 shared_bitmap_manager_.get(),
3383 gpu_memory_buffer_manager_.get(),
3384 NULL,
3386 false,
3387 1));
3389 id = resource_provider->CreateResource(
3390 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
3392 EXPECT_CALL(*context, createImageCHROMIUM(_, kWidth, kHeight, GL_RGBA))
3393 .WillOnce(Return(kImageId))
3394 .RetiresOnSaturation();
3396 ResourceProvider::ScopedWriteLockGpuMemoryBuffer lock(
3397 resource_provider.get(), id);
3398 EXPECT_TRUE(!!lock.GetGpuMemoryBuffer());
3401 EXPECT_CALL(*context, NextTextureId())
3402 .WillOnce(Return(kTextureId))
3403 .RetiresOnSaturation();
3404 // Once in CreateTextureId and once in BindForSampling
3405 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kTextureId)).Times(2)
3406 .RetiresOnSaturation();
3407 EXPECT_CALL(*context, bindTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId))
3408 .Times(1)
3409 .RetiresOnSaturation();
3411 ResourceProvider::ScopedSamplerGL lock_gl(
3412 resource_provider.get(), id, GL_TEXTURE_2D, GL_LINEAR);
3413 EXPECT_EQ(kTextureId, lock_gl.texture_id());
3417 ResourceProvider::ScopedWriteLockGpuMemoryBuffer lock(
3418 resource_provider.get(), id);
3419 EXPECT_TRUE(!!lock.GetGpuMemoryBuffer());
3422 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kTextureId)).Times(1)
3423 .RetiresOnSaturation();
3424 EXPECT_CALL(*context, releaseTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId))
3425 .Times(1)
3426 .RetiresOnSaturation();
3427 EXPECT_CALL(*context, bindTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId))
3428 .Times(1)
3429 .RetiresOnSaturation();
3430 EXPECT_CALL(*context, RetireTextureId(kTextureId))
3431 .Times(1)
3432 .RetiresOnSaturation();
3434 ResourceProvider::ScopedSamplerGL lock_gl(
3435 resource_provider.get(), id, GL_TEXTURE_2D, GL_LINEAR);
3436 EXPECT_EQ(kTextureId, lock_gl.texture_id());
3439 EXPECT_CALL(*context, destroyImageCHROMIUM(kImageId))
3440 .Times(1)
3441 .RetiresOnSaturation();
3444 TEST_P(ResourceProviderTest, CopyResource_GLTexture) {
3445 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
3446 return;
3447 scoped_ptr<AllocationTrackingContext3D> context_owned(
3448 new StrictMock<AllocationTrackingContext3D>);
3449 AllocationTrackingContext3D* context = context_owned.get();
3450 context_owned->set_support_sync_query(true);
3452 FakeOutputSurfaceClient output_surface_client;
3453 scoped_ptr<OutputSurface> output_surface(
3454 FakeOutputSurface::Create3d(context_owned.Pass()));
3455 ASSERT_TRUE(output_surface->BindToClient(&output_surface_client));
3457 const int kWidth = 2;
3458 const int kHeight = 2;
3459 gfx::Size size(kWidth, kHeight);
3460 ResourceFormat format = RGBA_8888;
3461 ResourceProvider::ResourceId source_id = 0;
3462 ResourceProvider::ResourceId dest_id = 0;
3463 const unsigned kSourceTextureId = 123u;
3464 const unsigned kDestTextureId = 321u;
3465 const unsigned kImageId = 234u;
3467 scoped_ptr<ResourceProvider> resource_provider(
3468 ResourceProvider::Create(output_surface.get(),
3469 shared_bitmap_manager_.get(),
3470 gpu_memory_buffer_manager_.get(),
3471 NULL,
3473 false,
3474 1));
3476 source_id = resource_provider->CreateResource(
3477 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
3479 EXPECT_CALL(*context, createImageCHROMIUM(_, kWidth, kHeight, GL_RGBA))
3480 .WillOnce(Return(kImageId))
3481 .RetiresOnSaturation();
3483 ResourceProvider::ScopedWriteLockGpuMemoryBuffer lock(
3484 resource_provider.get(), source_id);
3485 EXPECT_TRUE(!!lock.GetGpuMemoryBuffer());
3487 Mock::VerifyAndClearExpectations(context);
3489 dest_id = resource_provider->CreateResource(
3490 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
3492 EXPECT_CALL(*context, NextTextureId())
3493 .WillOnce(Return(kDestTextureId))
3494 .RetiresOnSaturation();
3495 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kDestTextureId))
3496 .Times(2)
3497 .RetiresOnSaturation();
3498 EXPECT_CALL(*context, texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA,
3499 GL_UNSIGNED_BYTE, nullptr))
3500 .Times(1)
3501 .RetiresOnSaturation();
3502 EXPECT_CALL(*context, NextTextureId())
3503 .WillOnce(Return(kSourceTextureId))
3504 .RetiresOnSaturation();
3505 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kSourceTextureId))
3506 .Times(2)
3507 .RetiresOnSaturation();
3508 EXPECT_CALL(*context, bindTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId))
3509 .Times(1)
3510 .RetiresOnSaturation();
3511 resource_provider->CopyResource(source_id, dest_id);
3512 Mock::VerifyAndClearExpectations(context);
3514 EXPECT_CALL(*context, destroyImageCHROMIUM(kImageId))
3515 .Times(1)
3516 .RetiresOnSaturation();
3517 EXPECT_CALL(*context, RetireTextureId(kSourceTextureId))
3518 .Times(1)
3519 .RetiresOnSaturation();
3520 EXPECT_CALL(*context, RetireTextureId(kDestTextureId))
3521 .Times(1)
3522 .RetiresOnSaturation();
3523 resource_provider->DeleteResource(source_id);
3524 resource_provider->DeleteResource(dest_id);
3527 void InitializeGLAndCheck(ContextSharedData* shared_data,
3528 ResourceProvider* resource_provider,
3529 FakeOutputSurface* output_surface) {
3530 scoped_ptr<ResourceProviderContext> context_owned =
3531 ResourceProviderContext::Create(shared_data);
3532 ResourceProviderContext* context = context_owned.get();
3534 scoped_refptr<TestContextProvider> context_provider =
3535 TestContextProvider::Create(context_owned.Pass());
3536 output_surface->InitializeAndSetContext3d(context_provider, nullptr);
3537 resource_provider->InitializeGL();
3539 CheckCreateResource(ResourceProvider::RESOURCE_TYPE_GL_TEXTURE,
3540 resource_provider, context);
3543 TEST(ResourceProviderTest, BasicInitializeGLSoftware) {
3544 scoped_ptr<ContextSharedData> shared_data = ContextSharedData::Create();
3545 bool delegated_rendering = false;
3546 scoped_ptr<FakeOutputSurface> output_surface(
3547 FakeOutputSurface::CreateDeferredGL(
3548 scoped_ptr<SoftwareOutputDevice>(new SoftwareOutputDevice),
3549 delegated_rendering));
3550 FakeOutputSurfaceClient client(output_surface.get());
3551 EXPECT_TRUE(output_surface->BindToClient(&client));
3552 scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
3553 new TestSharedBitmapManager());
3554 scoped_ptr<ResourceProvider> resource_provider(
3555 ResourceProvider::Create(output_surface.get(),
3556 shared_bitmap_manager.get(),
3557 NULL,
3558 NULL,
3560 false,
3561 1));
3563 CheckCreateResource(ResourceProvider::RESOURCE_TYPE_BITMAP,
3564 resource_provider.get(), NULL);
3566 InitializeGLAndCheck(shared_data.get(),
3567 resource_provider.get(),
3568 output_surface.get());
3570 resource_provider->InitializeSoftware();
3571 output_surface->ReleaseGL();
3572 CheckCreateResource(ResourceProvider::RESOURCE_TYPE_BITMAP,
3573 resource_provider.get(), NULL);
3575 InitializeGLAndCheck(shared_data.get(),
3576 resource_provider.get(),
3577 output_surface.get());
3580 TEST_P(ResourceProviderTest, CompressedTextureETC1Allocate) {
3581 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
3582 return;
3584 scoped_ptr<AllocationTrackingContext3D> context_owned(
3585 new AllocationTrackingContext3D);
3586 AllocationTrackingContext3D* context = context_owned.get();
3587 context_owned->set_support_compressed_texture_etc1(true);
3589 FakeOutputSurfaceClient output_surface_client;
3590 scoped_ptr<OutputSurface> output_surface(
3591 FakeOutputSurface::Create3d(context_owned.Pass()));
3592 CHECK(output_surface->BindToClient(&output_surface_client));
3594 gfx::Size size(4, 4);
3595 scoped_ptr<ResourceProvider> resource_provider(
3596 ResourceProvider::Create(output_surface.get(),
3597 shared_bitmap_manager_.get(),
3598 gpu_memory_buffer_manager_.get(),
3599 NULL,
3601 false,
3602 1));
3603 int texture_id = 123;
3605 ResourceProvider::ResourceId id = resource_provider->CreateResource(
3606 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, ETC1);
3607 EXPECT_NE(0u, id);
3608 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3609 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
3610 resource_provider->AllocateForTesting(id);
3612 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3613 resource_provider->DeleteResource(id);
3616 TEST_P(ResourceProviderTest, CompressedTextureETC1Upload) {
3617 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
3618 return;
3620 scoped_ptr<AllocationTrackingContext3D> context_owned(
3621 new AllocationTrackingContext3D);
3622 AllocationTrackingContext3D* context = context_owned.get();
3623 context_owned->set_support_compressed_texture_etc1(true);
3625 FakeOutputSurfaceClient output_surface_client;
3626 scoped_ptr<OutputSurface> output_surface(
3627 FakeOutputSurface::Create3d(context_owned.Pass()));
3628 CHECK(output_surface->BindToClient(&output_surface_client));
3630 gfx::Size size(4, 4);
3631 scoped_ptr<ResourceProvider> resource_provider(
3632 ResourceProvider::Create(output_surface.get(),
3633 shared_bitmap_manager_.get(),
3634 gpu_memory_buffer_manager_.get(),
3635 NULL,
3637 false,
3638 1));
3639 int texture_id = 123;
3640 uint8_t pixels[8];
3642 ResourceProvider::ResourceId id = resource_provider->CreateResource(
3643 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, ETC1);
3644 EXPECT_NE(0u, id);
3645 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3646 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(3);
3647 EXPECT_CALL(*context,
3648 compressedTexImage2D(
3649 _, 0, _, size.width(), size.height(), _, _, _)).Times(1);
3650 resource_provider->CopyToResource(id, pixels, size);
3652 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3653 resource_provider->DeleteResource(id);
3656 INSTANTIATE_TEST_CASE_P(
3657 ResourceProviderTests,
3658 ResourceProviderTest,
3659 ::testing::Values(ResourceProvider::RESOURCE_TYPE_GL_TEXTURE,
3660 ResourceProvider::RESOURCE_TYPE_BITMAP));
3662 class TextureIdAllocationTrackingContext : public TestWebGraphicsContext3D {
3663 public:
3664 GLuint NextTextureId() override {
3665 base::AutoLock lock(namespace_->lock);
3666 return namespace_->next_texture_id++;
3668 void RetireTextureId(GLuint) override {}
3669 GLuint PeekTextureId() {
3670 base::AutoLock lock(namespace_->lock);
3671 return namespace_->next_texture_id;
3675 TEST(ResourceProviderTest, TextureAllocationChunkSize) {
3676 scoped_ptr<TextureIdAllocationTrackingContext> context_owned(
3677 new TextureIdAllocationTrackingContext);
3678 TextureIdAllocationTrackingContext* context = context_owned.get();
3680 FakeOutputSurfaceClient output_surface_client;
3681 scoped_ptr<OutputSurface> output_surface(
3682 FakeOutputSurface::Create3d(context_owned.Pass()));
3683 CHECK(output_surface->BindToClient(&output_surface_client));
3684 scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
3685 new TestSharedBitmapManager());
3687 gfx::Size size(1, 1);
3688 ResourceFormat format = RGBA_8888;
3691 size_t kTextureAllocationChunkSize = 1;
3692 scoped_ptr<ResourceProvider> resource_provider(
3693 ResourceProvider::Create(output_surface.get(),
3694 shared_bitmap_manager.get(),
3695 NULL,
3696 NULL,
3698 false,
3699 kTextureAllocationChunkSize));
3701 ResourceProvider::ResourceId id = resource_provider->CreateResource(
3702 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE,
3703 format);
3704 resource_provider->AllocateForTesting(id);
3705 Mock::VerifyAndClearExpectations(context);
3707 DCHECK_EQ(2u, context->PeekTextureId());
3708 resource_provider->DeleteResource(id);
3712 size_t kTextureAllocationChunkSize = 8;
3713 scoped_ptr<ResourceProvider> resource_provider(
3714 ResourceProvider::Create(output_surface.get(),
3715 shared_bitmap_manager.get(),
3716 NULL,
3717 NULL,
3719 false,
3720 kTextureAllocationChunkSize));
3722 ResourceProvider::ResourceId id = resource_provider->CreateResource(
3723 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE,
3724 format);
3725 resource_provider->AllocateForTesting(id);
3726 Mock::VerifyAndClearExpectations(context);
3728 DCHECK_EQ(10u, context->PeekTextureId());
3729 resource_provider->DeleteResource(id);
3733 } // namespace
3734 } // namespace cc