ozone: evdev: Sync caps lock LED state to evdev
[chromium-blink-merge.git] / cc / resources / resource_provider_unittest.cc
blobfdd7fc0da760113e46ecfde488a66ddcf4413c69
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_METHOD2(produceTextureCHROMIUM,
101 void(GLenum target, const GLbyte* mailbox));
102 MOCK_METHOD2(consumeTextureCHROMIUM,
103 void(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 produceTextureCHROMIUM(GLenum target, const GLbyte* mailbox) override {
262 CheckTextureIsBound(target);
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 = BoundTexture(target);
271 pending_produce_textures_.push_back(pending.Pass());
274 void consumeTextureCHROMIUM(GLenum target, const GLbyte* mailbox) override {
275 CheckTextureIsBound(target);
276 base::AutoLock lock_for_texture_access(namespace_->lock);
277 scoped_refptr<TestTexture> texture =
278 shared_data_->ConsumeTexture(mailbox, last_waited_sync_point_);
279 namespace_->textures.Replace(BoundTextureId(target), texture);
282 void GetPixels(const gfx::Size& size,
283 ResourceFormat format,
284 uint8_t* pixels) {
285 CheckTextureIsBound(GL_TEXTURE_2D);
286 base::AutoLock lock_for_texture_access(namespace_->lock);
287 scoped_refptr<TestTexture> texture = BoundTexture(GL_TEXTURE_2D);
288 ASSERT_EQ(texture->size, size);
289 ASSERT_EQ(texture->format, format);
290 memcpy(pixels, texture->data.get(), TextureSizeBytes(size, format));
293 protected:
294 explicit ResourceProviderContext(ContextSharedData* shared_data)
295 : shared_data_(shared_data),
296 last_waited_sync_point_(0) {}
298 private:
299 void AllocateTexture(const gfx::Size& size, GLenum format) {
300 CheckTextureIsBound(GL_TEXTURE_2D);
301 ResourceFormat texture_format = RGBA_8888;
302 switch (format) {
303 case GL_RGBA:
304 texture_format = RGBA_8888;
305 break;
306 case GL_BGRA_EXT:
307 texture_format = BGRA_8888;
308 break;
310 base::AutoLock lock_for_texture_access(namespace_->lock);
311 BoundTexture(GL_TEXTURE_2D)->Reallocate(size, texture_format);
314 void SetPixels(int xoffset,
315 int yoffset,
316 int width,
317 int height,
318 const void* pixels) {
319 CheckTextureIsBound(GL_TEXTURE_2D);
320 base::AutoLock lock_for_texture_access(namespace_->lock);
321 scoped_refptr<TestTexture> texture = BoundTexture(GL_TEXTURE_2D);
322 ASSERT_TRUE(texture->data.get());
323 ASSERT_TRUE(xoffset >= 0 && xoffset + width <= texture->size.width());
324 ASSERT_TRUE(yoffset >= 0 && yoffset + height <= texture->size.height());
325 ASSERT_TRUE(pixels);
326 size_t in_pitch = TextureSizeBytes(gfx::Size(width, 1), texture->format);
327 size_t out_pitch =
328 TextureSizeBytes(gfx::Size(texture->size.width(), 1), texture->format);
329 uint8_t* dest = texture->data.get() + yoffset * out_pitch +
330 TextureSizeBytes(gfx::Size(xoffset, 1), texture->format);
331 const uint8_t* src = static_cast<const uint8_t*>(pixels);
332 for (int i = 0; i < height; ++i) {
333 memcpy(dest, src, in_pitch);
334 dest += out_pitch;
335 src += in_pitch;
339 struct PendingProduceTexture {
340 GLbyte mailbox[GL_MAILBOX_SIZE_CHROMIUM];
341 scoped_refptr<TestTexture> texture;
343 typedef ScopedPtrDeque<PendingProduceTexture> PendingProduceTextureList;
344 ContextSharedData* shared_data_;
345 GLuint last_waited_sync_point_;
346 PendingProduceTextureList pending_produce_textures_;
349 void GetResourcePixels(ResourceProvider* resource_provider,
350 ResourceProviderContext* context,
351 ResourceProvider::ResourceId id,
352 const gfx::Size& size,
353 ResourceFormat format,
354 uint8_t* pixels) {
355 resource_provider->WaitSyncPointIfNeeded(id);
356 switch (resource_provider->default_resource_type()) {
357 case ResourceProvider::RESOURCE_TYPE_GL_TEXTURE: {
358 ResourceProvider::ScopedReadLockGL lock_gl(resource_provider, id);
359 ASSERT_NE(0U, lock_gl.texture_id());
360 context->bindTexture(GL_TEXTURE_2D, lock_gl.texture_id());
361 context->GetPixels(size, format, pixels);
362 break;
364 case ResourceProvider::RESOURCE_TYPE_BITMAP: {
365 ResourceProvider::ScopedReadLockSoftware lock_software(resource_provider,
366 id);
367 memcpy(pixels,
368 lock_software.sk_bitmap()->getPixels(),
369 lock_software.sk_bitmap()->getSize());
370 break;
372 case ResourceProvider::RESOURCE_TYPE_INVALID:
373 NOTREACHED();
374 break;
378 class ResourceProviderTest
379 : public testing::TestWithParam<ResourceProvider::ResourceType> {
380 public:
381 ResourceProviderTest()
382 : shared_data_(ContextSharedData::Create()),
383 context3d_(NULL),
384 child_context_(NULL),
385 main_thread_task_runner_(BlockingTaskRunner::Create(NULL)) {
386 switch (GetParam()) {
387 case ResourceProvider::RESOURCE_TYPE_GL_TEXTURE: {
388 scoped_ptr<ResourceProviderContext> context3d(
389 ResourceProviderContext::Create(shared_data_.get()));
390 context3d_ = context3d.get();
392 scoped_refptr<TestContextProvider> context_provider =
393 TestContextProvider::Create(context3d.Pass());
395 output_surface_ = FakeOutputSurface::Create3d(context_provider);
397 scoped_ptr<ResourceProviderContext> child_context_owned =
398 ResourceProviderContext::Create(shared_data_.get());
399 child_context_ = child_context_owned.get();
400 child_output_surface_ =
401 FakeOutputSurface::Create3d(child_context_owned.Pass());
402 break;
404 case ResourceProvider::RESOURCE_TYPE_BITMAP:
405 output_surface_ = FakeOutputSurface::CreateSoftware(
406 make_scoped_ptr(new SoftwareOutputDevice));
407 child_output_surface_ = FakeOutputSurface::CreateSoftware(
408 make_scoped_ptr(new SoftwareOutputDevice));
409 break;
410 case ResourceProvider::RESOURCE_TYPE_INVALID:
411 NOTREACHED();
412 break;
414 CHECK(output_surface_->BindToClient(&output_surface_client_));
415 CHECK(child_output_surface_->BindToClient(&child_output_surface_client_));
417 shared_bitmap_manager_.reset(new TestSharedBitmapManager);
418 gpu_memory_buffer_manager_.reset(new TestGpuMemoryBufferManager);
420 resource_provider_ =
421 ResourceProvider::Create(output_surface_.get(),
422 shared_bitmap_manager_.get(),
423 gpu_memory_buffer_manager_.get(),
424 main_thread_task_runner_.get(),
426 false,
428 child_resource_provider_ =
429 ResourceProvider::Create(child_output_surface_.get(),
430 shared_bitmap_manager_.get(),
431 gpu_memory_buffer_manager_.get(),
432 main_thread_task_runner_.get(),
434 false,
438 static void CollectResources(ReturnedResourceArray* array,
439 const ReturnedResourceArray& returned,
440 BlockingTaskRunner* main_thread_task_runner) {
441 array->insert(array->end(), returned.begin(), returned.end());
444 static ReturnCallback GetReturnCallback(ReturnedResourceArray* array) {
445 return base::Bind(&ResourceProviderTest::CollectResources, array);
448 static void SetResourceFilter(ResourceProvider* resource_provider,
449 ResourceProvider::ResourceId id,
450 GLenum filter) {
451 ResourceProvider::ScopedSamplerGL sampler(
452 resource_provider, id, GL_TEXTURE_2D, filter);
455 ResourceProviderContext* context() { return context3d_; }
457 ResourceProvider::ResourceId CreateChildMailbox(uint32* release_sync_point,
458 bool* lost_resource,
459 bool* release_called,
460 uint32* sync_point) {
461 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) {
462 unsigned texture = child_context_->createTexture();
463 gpu::Mailbox gpu_mailbox;
464 child_context_->bindTexture(GL_TEXTURE_2D, texture);
465 child_context_->genMailboxCHROMIUM(gpu_mailbox.name);
466 child_context_->produceTextureCHROMIUM(GL_TEXTURE_2D, gpu_mailbox.name);
467 *sync_point = child_context_->insertSyncPoint();
468 EXPECT_LT(0u, *sync_point);
470 scoped_ptr<SharedBitmap> shared_bitmap;
471 scoped_ptr<SingleReleaseCallbackImpl> callback =
472 SingleReleaseCallbackImpl::Create(base::Bind(
473 ReleaseSharedBitmapCallback, base::Passed(&shared_bitmap),
474 release_called, release_sync_point, lost_resource));
475 return child_resource_provider_->CreateResourceFromTextureMailbox(
476 TextureMailbox(gpu_mailbox, GL_TEXTURE_2D, *sync_point),
477 callback.Pass());
478 } else {
479 gfx::Size size(64, 64);
480 scoped_ptr<SharedBitmap> shared_bitmap(
481 CreateAndFillSharedBitmap(shared_bitmap_manager_.get(), size, 0));
483 SharedBitmap* shared_bitmap_ptr = shared_bitmap.get();
484 scoped_ptr<SingleReleaseCallbackImpl> callback =
485 SingleReleaseCallbackImpl::Create(base::Bind(
486 ReleaseSharedBitmapCallback, base::Passed(&shared_bitmap),
487 release_called, release_sync_point, lost_resource));
488 return child_resource_provider_->CreateResourceFromTextureMailbox(
489 TextureMailbox(shared_bitmap_ptr, size), callback.Pass());
493 protected:
494 scoped_ptr<ContextSharedData> shared_data_;
495 ResourceProviderContext* context3d_;
496 ResourceProviderContext* child_context_;
497 FakeOutputSurfaceClient output_surface_client_;
498 FakeOutputSurfaceClient child_output_surface_client_;
499 scoped_ptr<OutputSurface> output_surface_;
500 scoped_ptr<OutputSurface> child_output_surface_;
501 scoped_ptr<BlockingTaskRunner> main_thread_task_runner_;
502 scoped_ptr<ResourceProvider> resource_provider_;
503 scoped_ptr<ResourceProvider> child_resource_provider_;
504 scoped_ptr<TestSharedBitmapManager> shared_bitmap_manager_;
505 scoped_ptr<TestGpuMemoryBufferManager> gpu_memory_buffer_manager_;
508 void CheckCreateResource(ResourceProvider::ResourceType expected_default_type,
509 ResourceProvider* resource_provider,
510 ResourceProviderContext* context) {
511 DCHECK_EQ(expected_default_type, resource_provider->default_resource_type());
513 gfx::Size size(1, 1);
514 ResourceFormat format = RGBA_8888;
515 size_t pixel_size = TextureSizeBytes(size, format);
516 ASSERT_EQ(4U, pixel_size);
518 ResourceProvider::ResourceId id = resource_provider->CreateResource(
519 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
520 EXPECT_EQ(1, static_cast<int>(resource_provider->num_resources()));
521 if (expected_default_type == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
522 EXPECT_EQ(0u, context->NumTextures());
524 uint8_t data[4] = { 1, 2, 3, 4 };
525 resource_provider->CopyToResource(id, data, size);
526 if (expected_default_type == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
527 EXPECT_EQ(1u, context->NumTextures());
529 uint8_t result[4] = { 0 };
530 GetResourcePixels(resource_provider, context, id, size, format, result);
531 EXPECT_EQ(0, memcmp(data, result, pixel_size));
533 resource_provider->DeleteResource(id);
534 EXPECT_EQ(0, static_cast<int>(resource_provider->num_resources()));
535 if (expected_default_type == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
536 EXPECT_EQ(0u, context->NumTextures());
539 TEST_P(ResourceProviderTest, Basic) {
540 CheckCreateResource(GetParam(), resource_provider_.get(), context());
543 TEST_P(ResourceProviderTest, Upload) {
544 gfx::Size size(2, 2);
545 ResourceFormat format = RGBA_8888;
546 size_t pixel_size = TextureSizeBytes(size, format);
547 ASSERT_EQ(16U, pixel_size);
549 ResourceProvider::ResourceId id = resource_provider_->CreateResource(
550 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
552 uint8_t image[16] = { 0 };
553 gfx::Rect image_rect(size);
554 resource_provider_->SetPixels(
555 id, image, image_rect, image_rect, gfx::Vector2d());
557 for (uint8_t i = 0; i < pixel_size; ++i)
558 image[i] = i;
560 uint8_t result[16] = { 0 };
562 gfx::Rect source_rect(0, 0, 1, 1);
563 gfx::Vector2d dest_offset(0, 0);
564 resource_provider_->SetPixels(
565 id, image, image_rect, source_rect, dest_offset);
567 uint8_t expected[16] = { 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
568 GetResourcePixels(
569 resource_provider_.get(), context(), id, size, format, result);
570 EXPECT_EQ(0, memcmp(expected, result, pixel_size));
573 gfx::Rect source_rect(0, 0, 1, 1);
574 gfx::Vector2d dest_offset(1, 1);
575 resource_provider_->SetPixels(
576 id, image, image_rect, source_rect, dest_offset);
578 uint8_t expected[16] = { 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3 };
579 GetResourcePixels(
580 resource_provider_.get(), context(), id, size, format, result);
581 EXPECT_EQ(0, memcmp(expected, result, pixel_size));
584 gfx::Rect source_rect(1, 0, 1, 1);
585 gfx::Vector2d dest_offset(0, 1);
586 resource_provider_->SetPixels(
587 id, image, image_rect, source_rect, dest_offset);
589 uint8_t expected[16] = { 0, 1, 2, 3, 0, 0, 0, 0, 4, 5, 6, 7, 0, 1, 2, 3 };
590 GetResourcePixels(
591 resource_provider_.get(), context(), id, size, format, result);
592 EXPECT_EQ(0, memcmp(expected, result, pixel_size));
595 gfx::Rect offset_image_rect(gfx::Point(100, 100), size);
596 gfx::Rect source_rect(100, 100, 1, 1);
597 gfx::Vector2d dest_offset(1, 0);
598 resource_provider_->SetPixels(
599 id, image, offset_image_rect, source_rect, dest_offset);
601 uint8_t expected[16] = { 0, 1, 2, 3, 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3 };
602 GetResourcePixels(
603 resource_provider_.get(), context(), id, size, format, result);
604 EXPECT_EQ(0, memcmp(expected, result, pixel_size));
607 resource_provider_->DeleteResource(id);
610 TEST_P(ResourceProviderTest, SimpleUpload) {
611 gfx::Size size(2, 2);
612 ResourceFormat format = RGBA_8888;
613 size_t pixel_size = TextureSizeBytes(size, format);
614 ASSERT_EQ(16U, pixel_size);
616 ResourceProvider::ResourceId id = resource_provider_->CreateResource(
617 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
619 uint8_t image[16] = {0};
620 resource_provider_->CopyToResource(id, image, size);
622 uint8_t result[16] = {0};
623 uint8_t expected[16] = {0};
624 GetResourcePixels(resource_provider_.get(), context(), id, size, format,
625 result);
626 EXPECT_EQ(0, memcmp(expected, result, pixel_size));
629 for (uint8_t i = 0; i < pixel_size; ++i)
630 image[i] = i;
631 resource_provider_->CopyToResource(id, image, size);
633 uint8_t result[16] = {0};
634 uint8_t expected[16] = {
635 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
636 GetResourcePixels(resource_provider_.get(), context(), id, size, format,
637 result);
638 EXPECT_EQ(0, memcmp(expected, result, pixel_size));
642 TEST_P(ResourceProviderTest, TransferGLResources) {
643 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
644 return;
645 gfx::Size size(1, 1);
646 ResourceFormat format = RGBA_8888;
647 size_t pixel_size = TextureSizeBytes(size, format);
648 ASSERT_EQ(4U, pixel_size);
650 ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource(
651 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
652 uint8_t data1[4] = { 1, 2, 3, 4 };
653 child_resource_provider_->CopyToResource(id1, data1, size);
655 ResourceProvider::ResourceId id2 = child_resource_provider_->CreateResource(
656 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
657 uint8_t data2[4] = { 5, 5, 5, 5 };
658 child_resource_provider_->CopyToResource(id2, data2, size);
660 ResourceProvider::ResourceId id3 = child_resource_provider_->CreateResource(
661 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
663 ResourceProvider::ScopedWriteLockGpuMemoryBuffer lock(
664 child_resource_provider_.get(), id3);
665 EXPECT_TRUE(!!lock.GetGpuMemoryBuffer());
668 GLuint external_texture_id = child_context_->createExternalTexture();
669 child_context_->bindTexture(GL_TEXTURE_EXTERNAL_OES, external_texture_id);
671 gpu::Mailbox external_mailbox;
672 child_context_->genMailboxCHROMIUM(external_mailbox.name);
673 child_context_->produceTextureCHROMIUM(GL_TEXTURE_EXTERNAL_OES,
674 external_mailbox.name);
675 const GLuint external_sync_point = child_context_->insertSyncPoint();
676 ResourceProvider::ResourceId id4 =
677 child_resource_provider_->CreateResourceFromTextureMailbox(
678 TextureMailbox(
679 external_mailbox, GL_TEXTURE_EXTERNAL_OES, external_sync_point),
680 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback)));
682 ReturnedResourceArray returned_to_child;
683 int child_id =
684 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
686 // Transfer some resources to the parent.
687 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
688 resource_ids_to_transfer.push_back(id1);
689 resource_ids_to_transfer.push_back(id2);
690 resource_ids_to_transfer.push_back(id3);
691 resource_ids_to_transfer.push_back(id4);
692 TransferableResourceArray list;
693 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
694 &list);
695 ASSERT_EQ(4u, list.size());
696 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
697 EXPECT_NE(0u, list[1].mailbox_holder.sync_point);
698 EXPECT_EQ(list[0].mailbox_holder.sync_point,
699 list[1].mailbox_holder.sync_point);
700 EXPECT_NE(0u, list[2].mailbox_holder.sync_point);
701 EXPECT_EQ(list[0].mailbox_holder.sync_point,
702 list[2].mailbox_holder.sync_point);
703 EXPECT_EQ(external_sync_point, list[3].mailbox_holder.sync_point);
704 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
705 list[0].mailbox_holder.texture_target);
706 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
707 list[1].mailbox_holder.texture_target);
708 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
709 list[2].mailbox_holder.texture_target);
710 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_EXTERNAL_OES),
711 list[3].mailbox_holder.texture_target);
712 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
713 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
714 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
715 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id4));
716 resource_provider_->ReceiveFromChild(child_id, list);
717 EXPECT_NE(list[0].mailbox_holder.sync_point,
718 context3d_->last_waited_sync_point());
720 resource_provider_->WaitSyncPointIfNeeded(list[0].id);
721 ResourceProvider::ScopedReadLockGL lock(resource_provider_.get(),
722 list[0].id);
724 EXPECT_EQ(list[0].mailbox_holder.sync_point,
725 context3d_->last_waited_sync_point());
726 resource_provider_->DeclareUsedResourcesFromChild(child_id,
727 resource_ids_to_transfer);
730 EXPECT_EQ(4u, resource_provider_->num_resources());
731 ResourceProvider::ResourceIdMap resource_map =
732 resource_provider_->GetChildToParentMap(child_id);
733 ResourceProvider::ResourceId mapped_id1 = resource_map[id1];
734 ResourceProvider::ResourceId mapped_id2 = resource_map[id2];
735 ResourceProvider::ResourceId mapped_id3 = resource_map[id3];
736 ResourceProvider::ResourceId mapped_id4 = resource_map[id4];
737 EXPECT_NE(0u, mapped_id1);
738 EXPECT_NE(0u, mapped_id2);
739 EXPECT_NE(0u, mapped_id3);
740 EXPECT_NE(0u, mapped_id4);
741 EXPECT_FALSE(resource_provider_->InUseByConsumer(id1));
742 EXPECT_FALSE(resource_provider_->InUseByConsumer(id2));
743 EXPECT_FALSE(resource_provider_->InUseByConsumer(id3));
744 EXPECT_FALSE(resource_provider_->InUseByConsumer(id4));
746 uint8_t result[4] = { 0 };
747 GetResourcePixels(
748 resource_provider_.get(), context(), mapped_id1, size, format, result);
749 EXPECT_EQ(0, memcmp(data1, result, pixel_size));
751 GetResourcePixels(
752 resource_provider_.get(), context(), mapped_id2, size, format, result);
753 EXPECT_EQ(0, memcmp(data2, result, pixel_size));
756 // Check that transfering again the same resource from the child to the
757 // parent works.
758 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
759 resource_ids_to_transfer.push_back(id1);
760 resource_ids_to_transfer.push_back(id2);
761 resource_ids_to_transfer.push_back(id3);
762 TransferableResourceArray list;
763 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
764 &list);
765 EXPECT_EQ(3u, list.size());
766 EXPECT_EQ(id1, list[0].id);
767 EXPECT_EQ(id2, list[1].id);
768 EXPECT_EQ(id3, list[2].id);
769 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
770 list[0].mailbox_holder.texture_target);
771 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
772 list[1].mailbox_holder.texture_target);
773 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
774 list[2].mailbox_holder.texture_target);
775 ReturnedResourceArray returned;
776 TransferableResource::ReturnResources(list, &returned);
777 child_resource_provider_->ReceiveReturnsFromParent(returned);
778 // ids were exported twice, we returned them only once, they should still
779 // be in-use.
780 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
781 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
782 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
785 EXPECT_EQ(0u, returned_to_child.size());
787 // Transfer resources back from the parent to the child. Set no resources as
788 // being in use.
789 ResourceProvider::ResourceIdArray no_resources;
790 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
792 ASSERT_EQ(4u, returned_to_child.size());
793 EXPECT_NE(0u, returned_to_child[0].sync_point);
794 EXPECT_NE(0u, returned_to_child[1].sync_point);
795 EXPECT_NE(0u, returned_to_child[2].sync_point);
796 EXPECT_NE(0u, returned_to_child[3].sync_point);
797 EXPECT_FALSE(returned_to_child[0].lost);
798 EXPECT_FALSE(returned_to_child[1].lost);
799 EXPECT_FALSE(returned_to_child[2].lost);
800 EXPECT_FALSE(returned_to_child[3].lost);
801 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
802 returned_to_child.clear();
804 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id1));
805 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id2));
806 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id3));
807 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id4));
810 child_resource_provider_->WaitSyncPointIfNeeded(id1);
811 ResourceProvider::ScopedReadLockGL lock(child_resource_provider_.get(),
812 id1);
813 ASSERT_NE(0U, lock.texture_id());
814 child_context_->bindTexture(GL_TEXTURE_2D, lock.texture_id());
815 child_context_->GetPixels(size, format, result);
816 EXPECT_EQ(0, memcmp(data1, result, pixel_size));
819 child_resource_provider_->WaitSyncPointIfNeeded(id2);
820 ResourceProvider::ScopedReadLockGL lock(child_resource_provider_.get(),
821 id2);
822 ASSERT_NE(0U, lock.texture_id());
823 child_context_->bindTexture(GL_TEXTURE_2D, lock.texture_id());
824 child_context_->GetPixels(size, format, result);
825 EXPECT_EQ(0, memcmp(data2, result, pixel_size));
828 child_resource_provider_->WaitSyncPointIfNeeded(id3);
829 ResourceProvider::ScopedReadLockGL lock(child_resource_provider_.get(),
830 id3);
831 ASSERT_NE(0U, lock.texture_id());
832 child_context_->bindTexture(GL_TEXTURE_2D, lock.texture_id());
835 // Transfer resources to the parent again.
836 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
837 resource_ids_to_transfer.push_back(id1);
838 resource_ids_to_transfer.push_back(id2);
839 resource_ids_to_transfer.push_back(id3);
840 resource_ids_to_transfer.push_back(id4);
841 TransferableResourceArray list;
842 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
843 &list);
844 ASSERT_EQ(4u, list.size());
845 EXPECT_EQ(id1, list[0].id);
846 EXPECT_EQ(id2, list[1].id);
847 EXPECT_EQ(id3, list[2].id);
848 EXPECT_EQ(id4, list[3].id);
849 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
850 EXPECT_NE(0u, list[1].mailbox_holder.sync_point);
851 EXPECT_NE(0u, list[2].mailbox_holder.sync_point);
852 EXPECT_NE(0u, list[3].mailbox_holder.sync_point);
853 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
854 list[0].mailbox_holder.texture_target);
855 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
856 list[1].mailbox_holder.texture_target);
857 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
858 list[2].mailbox_holder.texture_target);
859 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_EXTERNAL_OES),
860 list[3].mailbox_holder.texture_target);
861 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
862 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
863 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
864 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id4));
865 resource_provider_->ReceiveFromChild(child_id, list);
866 resource_provider_->DeclareUsedResourcesFromChild(child_id,
867 resource_ids_to_transfer);
870 EXPECT_EQ(0u, returned_to_child.size());
872 EXPECT_EQ(4u, resource_provider_->num_resources());
873 resource_provider_->DestroyChild(child_id);
874 EXPECT_EQ(0u, resource_provider_->num_resources());
876 ASSERT_EQ(4u, returned_to_child.size());
877 EXPECT_NE(0u, returned_to_child[0].sync_point);
878 EXPECT_NE(0u, returned_to_child[1].sync_point);
879 EXPECT_NE(0u, returned_to_child[2].sync_point);
880 EXPECT_NE(0u, returned_to_child[3].sync_point);
881 EXPECT_FALSE(returned_to_child[0].lost);
882 EXPECT_FALSE(returned_to_child[1].lost);
883 EXPECT_FALSE(returned_to_child[2].lost);
884 EXPECT_FALSE(returned_to_child[3].lost);
887 TEST_P(ResourceProviderTest, ReadLockCountStopsReturnToChildOrDelete) {
888 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
889 return;
890 gfx::Size size(1, 1);
891 ResourceFormat format = RGBA_8888;
893 ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource(
894 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
895 uint8_t data1[4] = {1, 2, 3, 4};
896 child_resource_provider_->CopyToResource(id1, data1, size);
898 ReturnedResourceArray returned_to_child;
899 int child_id =
900 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
902 // Transfer some resources to the parent.
903 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
904 resource_ids_to_transfer.push_back(id1);
905 TransferableResourceArray list;
906 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
907 &list);
908 ASSERT_EQ(1u, list.size());
909 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
911 resource_provider_->ReceiveFromChild(child_id, list);
913 resource_provider_->WaitSyncPointIfNeeded(list[0].id);
914 ResourceProvider::ScopedReadLockGL lock(resource_provider_.get(),
915 list[0].id);
917 resource_provider_->DeclareUsedResourcesFromChild(
918 child_id, ResourceProvider::ResourceIdArray());
919 EXPECT_EQ(0u, returned_to_child.size());
922 EXPECT_EQ(1u, returned_to_child.size());
923 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
926 child_resource_provider_->WaitSyncPointIfNeeded(id1);
927 ResourceProvider::ScopedReadLockGL lock(child_resource_provider_.get(),
928 id1);
929 child_resource_provider_->DeleteResource(id1);
930 EXPECT_EQ(1u, child_resource_provider_->num_resources());
931 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
934 EXPECT_EQ(0u, child_resource_provider_->num_resources());
935 resource_provider_->DestroyChild(child_id);
938 TEST_P(ResourceProviderTest, AllowOverlayTransfersToParent) {
939 // Overlays only supported on the GL path.
940 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
941 return;
943 uint32 sync_point = 0;
944 TextureMailbox mailbox(gpu::Mailbox::Generate(), GL_TEXTURE_2D, sync_point);
945 mailbox.set_allow_overlay(true);
946 scoped_ptr<SingleReleaseCallbackImpl> release_callback =
947 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback));
948 ResourceProvider::ResourceId id1 =
949 child_resource_provider_->CreateResourceFromTextureMailbox(
950 mailbox, release_callback.Pass());
952 TextureMailbox mailbox2(gpu::Mailbox::Generate(), GL_TEXTURE_2D, sync_point);
953 mailbox2.set_allow_overlay(false);
954 scoped_ptr<SingleReleaseCallbackImpl> release_callback2 =
955 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback));
956 ResourceProvider::ResourceId id2 =
957 child_resource_provider_->CreateResourceFromTextureMailbox(
958 mailbox2, release_callback2.Pass());
960 ReturnedResourceArray returned_to_child;
961 int child_id =
962 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
964 // Transfer some resources to the parent.
965 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
966 resource_ids_to_transfer.push_back(id1);
967 resource_ids_to_transfer.push_back(id2);
968 TransferableResourceArray list;
969 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
970 &list);
971 ASSERT_EQ(2u, list.size());
972 resource_provider_->ReceiveFromChild(child_id, list);
973 EXPECT_TRUE(resource_provider_->AllowOverlay(list[0].id));
974 EXPECT_FALSE(resource_provider_->AllowOverlay(list[1].id));
976 resource_provider_->DeclareUsedResourcesFromChild(
977 child_id, ResourceProvider::ResourceIdArray());
979 EXPECT_EQ(2u, returned_to_child.size());
980 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
982 child_resource_provider_->DeleteResource(id1);
983 child_resource_provider_->DeleteResource(id2);
984 EXPECT_EQ(0u, child_resource_provider_->num_resources());
986 resource_provider_->DestroyChild(child_id);
989 TEST_P(ResourceProviderTest, TransferSoftwareResources) {
990 if (GetParam() != ResourceProvider::RESOURCE_TYPE_BITMAP)
991 return;
993 gfx::Size size(1, 1);
994 ResourceFormat format = RGBA_8888;
995 size_t pixel_size = TextureSizeBytes(size, format);
996 ASSERT_EQ(4U, pixel_size);
998 ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource(
999 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
1000 uint8_t data1[4] = { 1, 2, 3, 4 };
1001 child_resource_provider_->CopyToResource(id1, data1, size);
1003 ResourceProvider::ResourceId id2 = child_resource_provider_->CreateResource(
1004 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
1005 uint8_t data2[4] = { 5, 5, 5, 5 };
1006 child_resource_provider_->CopyToResource(id2, data2, size);
1008 scoped_ptr<SharedBitmap> shared_bitmap(CreateAndFillSharedBitmap(
1009 shared_bitmap_manager_.get(), gfx::Size(1, 1), 0));
1010 SharedBitmap* shared_bitmap_ptr = shared_bitmap.get();
1011 ResourceProvider::ResourceId id3 =
1012 child_resource_provider_->CreateResourceFromTextureMailbox(
1013 TextureMailbox(shared_bitmap_ptr, gfx::Size(1, 1)),
1014 SingleReleaseCallbackImpl::Create(base::Bind(
1015 &SharedBitmapReleaseCallback, base::Passed(&shared_bitmap))));
1017 ReturnedResourceArray returned_to_child;
1018 int child_id =
1019 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1021 // Transfer some resources to the parent.
1022 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1023 resource_ids_to_transfer.push_back(id1);
1024 resource_ids_to_transfer.push_back(id2);
1025 resource_ids_to_transfer.push_back(id3);
1026 TransferableResourceArray list;
1027 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1028 &list);
1029 ASSERT_EQ(3u, list.size());
1030 EXPECT_EQ(0u, list[0].mailbox_holder.sync_point);
1031 EXPECT_EQ(0u, list[1].mailbox_holder.sync_point);
1032 EXPECT_EQ(0u, list[2].mailbox_holder.sync_point);
1033 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1034 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
1035 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
1036 resource_provider_->ReceiveFromChild(child_id, list);
1037 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1038 resource_ids_to_transfer);
1041 EXPECT_EQ(3u, resource_provider_->num_resources());
1042 ResourceProvider::ResourceIdMap resource_map =
1043 resource_provider_->GetChildToParentMap(child_id);
1044 ResourceProvider::ResourceId mapped_id1 = resource_map[id1];
1045 ResourceProvider::ResourceId mapped_id2 = resource_map[id2];
1046 ResourceProvider::ResourceId mapped_id3 = resource_map[id3];
1047 EXPECT_NE(0u, mapped_id1);
1048 EXPECT_NE(0u, mapped_id2);
1049 EXPECT_NE(0u, mapped_id3);
1050 EXPECT_FALSE(resource_provider_->InUseByConsumer(id1));
1051 EXPECT_FALSE(resource_provider_->InUseByConsumer(id2));
1052 EXPECT_FALSE(resource_provider_->InUseByConsumer(id3));
1054 uint8_t result[4] = { 0 };
1055 GetResourcePixels(
1056 resource_provider_.get(), context(), mapped_id1, size, format, result);
1057 EXPECT_EQ(0, memcmp(data1, result, pixel_size));
1059 GetResourcePixels(
1060 resource_provider_.get(), context(), mapped_id2, size, format, result);
1061 EXPECT_EQ(0, memcmp(data2, result, pixel_size));
1064 // Check that transfering again the same resource from the child to the
1065 // parent works.
1066 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1067 resource_ids_to_transfer.push_back(id1);
1068 resource_ids_to_transfer.push_back(id2);
1069 TransferableResourceArray list;
1070 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1071 &list);
1072 EXPECT_EQ(2u, list.size());
1073 EXPECT_EQ(id1, list[0].id);
1074 EXPECT_EQ(id2, list[1].id);
1075 ReturnedResourceArray returned;
1076 TransferableResource::ReturnResources(list, &returned);
1077 child_resource_provider_->ReceiveReturnsFromParent(returned);
1078 // ids were exported twice, we returned them only once, they should still
1079 // be in-use.
1080 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1081 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
1084 EXPECT_EQ(0u, returned_to_child.size());
1086 // Transfer resources back from the parent to the child. Set no resources as
1087 // being in use.
1088 ResourceProvider::ResourceIdArray no_resources;
1089 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
1091 ASSERT_EQ(3u, returned_to_child.size());
1092 EXPECT_EQ(0u, returned_to_child[0].sync_point);
1093 EXPECT_EQ(0u, returned_to_child[1].sync_point);
1094 EXPECT_EQ(0u, returned_to_child[2].sync_point);
1095 std::set<ResourceProvider::ResourceId> expected_ids;
1096 expected_ids.insert(id1);
1097 expected_ids.insert(id2);
1098 expected_ids.insert(id3);
1099 std::set<ResourceProvider::ResourceId> returned_ids;
1100 for (unsigned i = 0; i < 3; i++)
1101 returned_ids.insert(returned_to_child[i].id);
1102 EXPECT_EQ(expected_ids, returned_ids);
1103 EXPECT_FALSE(returned_to_child[0].lost);
1104 EXPECT_FALSE(returned_to_child[1].lost);
1105 EXPECT_FALSE(returned_to_child[2].lost);
1106 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
1107 returned_to_child.clear();
1109 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id1));
1110 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id2));
1111 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id3));
1114 ResourceProvider::ScopedReadLockSoftware lock(
1115 child_resource_provider_.get(), id1);
1116 const SkBitmap* sk_bitmap = lock.sk_bitmap();
1117 EXPECT_EQ(sk_bitmap->width(), size.width());
1118 EXPECT_EQ(sk_bitmap->height(), size.height());
1119 EXPECT_EQ(0, memcmp(data1, sk_bitmap->getPixels(), pixel_size));
1122 ResourceProvider::ScopedReadLockSoftware lock(
1123 child_resource_provider_.get(), id2);
1124 const SkBitmap* sk_bitmap = lock.sk_bitmap();
1125 EXPECT_EQ(sk_bitmap->width(), size.width());
1126 EXPECT_EQ(sk_bitmap->height(), size.height());
1127 EXPECT_EQ(0, memcmp(data2, sk_bitmap->getPixels(), pixel_size));
1130 // Transfer resources to the parent again.
1131 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1132 resource_ids_to_transfer.push_back(id1);
1133 resource_ids_to_transfer.push_back(id2);
1134 resource_ids_to_transfer.push_back(id3);
1135 TransferableResourceArray list;
1136 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1137 &list);
1138 ASSERT_EQ(3u, list.size());
1139 EXPECT_EQ(id1, list[0].id);
1140 EXPECT_EQ(id2, list[1].id);
1141 EXPECT_EQ(id3, list[2].id);
1142 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1143 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
1144 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
1145 resource_provider_->ReceiveFromChild(child_id, list);
1146 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1147 resource_ids_to_transfer);
1150 EXPECT_EQ(0u, returned_to_child.size());
1152 EXPECT_EQ(3u, resource_provider_->num_resources());
1153 resource_provider_->DestroyChild(child_id);
1154 EXPECT_EQ(0u, resource_provider_->num_resources());
1156 ASSERT_EQ(3u, returned_to_child.size());
1157 EXPECT_EQ(0u, returned_to_child[0].sync_point);
1158 EXPECT_EQ(0u, returned_to_child[1].sync_point);
1159 EXPECT_EQ(0u, returned_to_child[2].sync_point);
1160 std::set<ResourceProvider::ResourceId> expected_ids;
1161 expected_ids.insert(id1);
1162 expected_ids.insert(id2);
1163 expected_ids.insert(id3);
1164 std::set<ResourceProvider::ResourceId> returned_ids;
1165 for (unsigned i = 0; i < 3; i++)
1166 returned_ids.insert(returned_to_child[i].id);
1167 EXPECT_EQ(expected_ids, returned_ids);
1168 EXPECT_FALSE(returned_to_child[0].lost);
1169 EXPECT_FALSE(returned_to_child[1].lost);
1170 EXPECT_FALSE(returned_to_child[2].lost);
1173 TEST_P(ResourceProviderTest, TransferGLToSoftware) {
1174 if (GetParam() != ResourceProvider::RESOURCE_TYPE_BITMAP)
1175 return;
1177 scoped_ptr<ResourceProviderContext> child_context_owned(
1178 ResourceProviderContext::Create(shared_data_.get()));
1180 FakeOutputSurfaceClient child_output_surface_client;
1181 scoped_ptr<OutputSurface> child_output_surface(
1182 FakeOutputSurface::Create3d(child_context_owned.Pass()));
1183 CHECK(child_output_surface->BindToClient(&child_output_surface_client));
1185 scoped_ptr<ResourceProvider> child_resource_provider(
1186 ResourceProvider::Create(child_output_surface.get(),
1187 shared_bitmap_manager_.get(),
1188 gpu_memory_buffer_manager_.get(),
1189 NULL,
1191 false,
1192 1));
1194 gfx::Size size(1, 1);
1195 ResourceFormat format = RGBA_8888;
1196 size_t pixel_size = TextureSizeBytes(size, format);
1197 ASSERT_EQ(4U, pixel_size);
1199 ResourceProvider::ResourceId id1 = child_resource_provider->CreateResource(
1200 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
1201 uint8_t data1[4] = { 1, 2, 3, 4 };
1202 child_resource_provider->CopyToResource(id1, data1, size);
1204 ReturnedResourceArray returned_to_child;
1205 int child_id =
1206 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1208 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1209 resource_ids_to_transfer.push_back(id1);
1210 TransferableResourceArray list;
1211 child_resource_provider->PrepareSendToParent(resource_ids_to_transfer,
1212 &list);
1213 ASSERT_EQ(1u, list.size());
1214 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
1215 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
1216 list[0].mailbox_holder.texture_target);
1217 EXPECT_TRUE(child_resource_provider->InUseByConsumer(id1));
1218 resource_provider_->ReceiveFromChild(child_id, list);
1221 EXPECT_EQ(0u, resource_provider_->num_resources());
1222 ASSERT_EQ(1u, returned_to_child.size());
1223 EXPECT_EQ(returned_to_child[0].id, id1);
1224 ResourceProvider::ResourceIdMap resource_map =
1225 resource_provider_->GetChildToParentMap(child_id);
1226 ResourceProvider::ResourceId mapped_id1 = resource_map[id1];
1227 EXPECT_EQ(0u, mapped_id1);
1229 resource_provider_->DestroyChild(child_id);
1230 EXPECT_EQ(0u, resource_provider_->num_resources());
1232 ASSERT_EQ(1u, returned_to_child.size());
1233 EXPECT_FALSE(returned_to_child[0].lost);
1236 TEST_P(ResourceProviderTest, TransferInvalidSoftware) {
1237 if (GetParam() != ResourceProvider::RESOURCE_TYPE_BITMAP)
1238 return;
1240 gfx::Size size(1, 1);
1241 ResourceFormat format = RGBA_8888;
1242 size_t pixel_size = TextureSizeBytes(size, format);
1243 ASSERT_EQ(4U, pixel_size);
1245 ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource(
1246 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
1247 uint8_t data1[4] = { 1, 2, 3, 4 };
1248 child_resource_provider_->CopyToResource(id1, data1, size);
1250 ReturnedResourceArray returned_to_child;
1251 int child_id =
1252 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1254 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1255 resource_ids_to_transfer.push_back(id1);
1256 TransferableResourceArray list;
1257 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1258 &list);
1259 ASSERT_EQ(1u, list.size());
1260 // Make invalid.
1261 list[0].mailbox_holder.mailbox.name[1] = 5;
1262 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1263 resource_provider_->ReceiveFromChild(child_id, list);
1266 EXPECT_EQ(1u, resource_provider_->num_resources());
1267 EXPECT_EQ(0u, returned_to_child.size());
1269 ResourceProvider::ResourceIdMap resource_map =
1270 resource_provider_->GetChildToParentMap(child_id);
1271 ResourceProvider::ResourceId mapped_id1 = resource_map[id1];
1272 EXPECT_NE(0u, mapped_id1);
1274 ResourceProvider::ScopedReadLockSoftware lock(resource_provider_.get(),
1275 mapped_id1);
1276 EXPECT_FALSE(lock.valid());
1279 resource_provider_->DestroyChild(child_id);
1280 EXPECT_EQ(0u, resource_provider_->num_resources());
1282 ASSERT_EQ(1u, returned_to_child.size());
1283 EXPECT_FALSE(returned_to_child[0].lost);
1286 TEST_P(ResourceProviderTest, DeleteExportedResources) {
1287 gfx::Size size(1, 1);
1288 ResourceFormat format = RGBA_8888;
1289 size_t pixel_size = TextureSizeBytes(size, format);
1290 ASSERT_EQ(4U, pixel_size);
1292 ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource(
1293 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
1294 uint8_t data1[4] = { 1, 2, 3, 4 };
1295 child_resource_provider_->CopyToResource(id1, data1, size);
1297 ResourceProvider::ResourceId id2 = child_resource_provider_->CreateResource(
1298 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
1299 uint8_t data2[4] = {5, 5, 5, 5};
1300 child_resource_provider_->CopyToResource(id2, data2, size);
1302 ReturnedResourceArray returned_to_child;
1303 int child_id =
1304 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1306 // Transfer some resources to the parent.
1307 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1308 resource_ids_to_transfer.push_back(id1);
1309 resource_ids_to_transfer.push_back(id2);
1310 TransferableResourceArray list;
1311 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1312 &list);
1313 ASSERT_EQ(2u, list.size());
1314 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) {
1315 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
1316 EXPECT_NE(0u, list[1].mailbox_holder.sync_point);
1318 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1319 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
1320 resource_provider_->ReceiveFromChild(child_id, list);
1321 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1322 resource_ids_to_transfer);
1325 EXPECT_EQ(2u, resource_provider_->num_resources());
1326 ResourceProvider::ResourceIdMap resource_map =
1327 resource_provider_->GetChildToParentMap(child_id);
1328 ResourceProvider::ResourceId mapped_id1 = resource_map[id1];
1329 ResourceProvider::ResourceId mapped_id2 = resource_map[id2];
1330 EXPECT_NE(0u, mapped_id1);
1331 EXPECT_NE(0u, mapped_id2);
1332 EXPECT_FALSE(resource_provider_->InUseByConsumer(id1));
1333 EXPECT_FALSE(resource_provider_->InUseByConsumer(id2));
1336 // The parent transfers the resources to the grandparent.
1337 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1338 resource_ids_to_transfer.push_back(mapped_id1);
1339 resource_ids_to_transfer.push_back(mapped_id2);
1340 TransferableResourceArray list;
1341 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
1343 ASSERT_EQ(2u, list.size());
1344 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) {
1345 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
1346 EXPECT_NE(0u, list[1].mailbox_holder.sync_point);
1348 EXPECT_TRUE(resource_provider_->InUseByConsumer(id1));
1349 EXPECT_TRUE(resource_provider_->InUseByConsumer(id2));
1351 // Release the resource in the parent. Set no resources as being in use. The
1352 // resources are exported so that can't be transferred back yet.
1353 ResourceProvider::ResourceIdArray no_resources;
1354 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
1356 EXPECT_EQ(0u, returned_to_child.size());
1357 EXPECT_EQ(2u, resource_provider_->num_resources());
1359 // Return the resources from the grandparent to the parent. They should be
1360 // returned to the child then.
1361 EXPECT_EQ(2u, list.size());
1362 EXPECT_EQ(mapped_id1, list[0].id);
1363 EXPECT_EQ(mapped_id2, list[1].id);
1364 ReturnedResourceArray returned;
1365 TransferableResource::ReturnResources(list, &returned);
1366 resource_provider_->ReceiveReturnsFromParent(returned);
1368 EXPECT_EQ(0u, resource_provider_->num_resources());
1369 ASSERT_EQ(2u, returned_to_child.size());
1370 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) {
1371 EXPECT_NE(0u, returned_to_child[0].sync_point);
1372 EXPECT_NE(0u, returned_to_child[1].sync_point);
1374 EXPECT_FALSE(returned_to_child[0].lost);
1375 EXPECT_FALSE(returned_to_child[1].lost);
1379 TEST_P(ResourceProviderTest, DestroyChildWithExportedResources) {
1380 gfx::Size size(1, 1);
1381 ResourceFormat format = RGBA_8888;
1382 size_t pixel_size = TextureSizeBytes(size, format);
1383 ASSERT_EQ(4U, pixel_size);
1385 ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource(
1386 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
1387 uint8_t data1[4] = {1, 2, 3, 4};
1388 child_resource_provider_->CopyToResource(id1, data1, size);
1390 ResourceProvider::ResourceId id2 = child_resource_provider_->CreateResource(
1391 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
1392 uint8_t data2[4] = {5, 5, 5, 5};
1393 child_resource_provider_->CopyToResource(id2, data2, size);
1395 ReturnedResourceArray returned_to_child;
1396 int child_id =
1397 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1399 // Transfer some resources to the parent.
1400 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1401 resource_ids_to_transfer.push_back(id1);
1402 resource_ids_to_transfer.push_back(id2);
1403 TransferableResourceArray list;
1404 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1405 &list);
1406 ASSERT_EQ(2u, list.size());
1407 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) {
1408 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
1409 EXPECT_NE(0u, list[1].mailbox_holder.sync_point);
1411 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1412 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
1413 resource_provider_->ReceiveFromChild(child_id, list);
1414 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1415 resource_ids_to_transfer);
1418 EXPECT_EQ(2u, resource_provider_->num_resources());
1419 ResourceProvider::ResourceIdMap resource_map =
1420 resource_provider_->GetChildToParentMap(child_id);
1421 ResourceProvider::ResourceId mapped_id1 = resource_map[id1];
1422 ResourceProvider::ResourceId mapped_id2 = resource_map[id2];
1423 EXPECT_NE(0u, mapped_id1);
1424 EXPECT_NE(0u, mapped_id2);
1425 EXPECT_FALSE(resource_provider_->InUseByConsumer(id1));
1426 EXPECT_FALSE(resource_provider_->InUseByConsumer(id2));
1429 // The parent transfers the resources to the grandparent.
1430 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1431 resource_ids_to_transfer.push_back(mapped_id1);
1432 resource_ids_to_transfer.push_back(mapped_id2);
1433 TransferableResourceArray list;
1434 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
1436 ASSERT_EQ(2u, list.size());
1437 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) {
1438 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
1439 EXPECT_NE(0u, list[1].mailbox_holder.sync_point);
1441 EXPECT_TRUE(resource_provider_->InUseByConsumer(id1));
1442 EXPECT_TRUE(resource_provider_->InUseByConsumer(id2));
1444 // Release the resource in the parent. Set no resources as being in use. The
1445 // resources are exported so that can't be transferred back yet.
1446 ResourceProvider::ResourceIdArray no_resources;
1447 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
1449 // Destroy the child, the resources should not be returned yet.
1450 EXPECT_EQ(0u, returned_to_child.size());
1451 EXPECT_EQ(2u, resource_provider_->num_resources());
1453 resource_provider_->DestroyChild(child_id);
1455 EXPECT_EQ(2u, resource_provider_->num_resources());
1456 ASSERT_EQ(0u, returned_to_child.size());
1458 // Return a resource from the grandparent, it should be returned at this
1459 // point.
1460 EXPECT_EQ(2u, list.size());
1461 EXPECT_EQ(mapped_id1, list[0].id);
1462 EXPECT_EQ(mapped_id2, list[1].id);
1463 TransferableResourceArray return_list;
1464 return_list.push_back(list[1]);
1465 list.pop_back();
1466 ReturnedResourceArray returned;
1467 TransferableResource::ReturnResources(return_list, &returned);
1468 resource_provider_->ReceiveReturnsFromParent(returned);
1470 EXPECT_EQ(1u, resource_provider_->num_resources());
1471 ASSERT_EQ(1u, returned_to_child.size());
1472 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) {
1473 EXPECT_NE(0u, returned_to_child[0].sync_point);
1475 EXPECT_FALSE(returned_to_child[0].lost);
1476 returned_to_child.clear();
1478 // Destroy the parent resource provider. The resource that's left should be
1479 // lost at this point, and returned.
1480 resource_provider_ = nullptr;
1481 ASSERT_EQ(1u, returned_to_child.size());
1482 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) {
1483 EXPECT_NE(0u, returned_to_child[0].sync_point);
1485 EXPECT_TRUE(returned_to_child[0].lost);
1489 TEST_P(ResourceProviderTest, DeleteTransferredResources) {
1490 gfx::Size size(1, 1);
1491 ResourceFormat format = RGBA_8888;
1492 size_t pixel_size = TextureSizeBytes(size, format);
1493 ASSERT_EQ(4U, pixel_size);
1495 ResourceProvider::ResourceId id = child_resource_provider_->CreateResource(
1496 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
1497 uint8_t data[4] = { 1, 2, 3, 4 };
1498 child_resource_provider_->CopyToResource(id, data, size);
1500 ReturnedResourceArray returned_to_child;
1501 int child_id =
1502 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1504 // Transfer some resource to the parent.
1505 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1506 resource_ids_to_transfer.push_back(id);
1507 TransferableResourceArray list;
1508 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1509 &list);
1510 ASSERT_EQ(1u, list.size());
1511 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
1512 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
1513 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id));
1514 resource_provider_->ReceiveFromChild(child_id, list);
1515 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1516 resource_ids_to_transfer);
1519 // Delete textures in the child, while they are transfered.
1520 child_resource_provider_->DeleteResource(id);
1521 EXPECT_EQ(1u, child_resource_provider_->num_resources());
1523 EXPECT_EQ(0u, returned_to_child.size());
1525 // Transfer resources back from the parent to the child. Set no resources as
1526 // being in use.
1527 ResourceProvider::ResourceIdArray no_resources;
1528 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
1530 ASSERT_EQ(1u, returned_to_child.size());
1531 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
1532 EXPECT_NE(0u, returned_to_child[0].sync_point);
1533 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
1535 EXPECT_EQ(0u, child_resource_provider_->num_resources());
1538 TEST_P(ResourceProviderTest, UnuseTransferredResources) {
1539 gfx::Size size(1, 1);
1540 ResourceFormat format = RGBA_8888;
1541 size_t pixel_size = TextureSizeBytes(size, format);
1542 ASSERT_EQ(4U, pixel_size);
1544 ResourceProvider::ResourceId id = child_resource_provider_->CreateResource(
1545 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
1546 uint8_t data[4] = {1, 2, 3, 4};
1547 child_resource_provider_->CopyToResource(id, data, size);
1549 ReturnedResourceArray returned_to_child;
1550 int child_id =
1551 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1552 const ResourceProvider::ResourceIdMap& map =
1553 resource_provider_->GetChildToParentMap(child_id);
1555 // Transfer some resource to the parent.
1556 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1557 resource_ids_to_transfer.push_back(id);
1558 TransferableResourceArray list;
1559 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1560 &list);
1561 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id));
1562 resource_provider_->ReceiveFromChild(child_id, list);
1563 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1564 resource_ids_to_transfer);
1566 TransferableResourceArray sent_to_top_level;
1568 // Parent transfers to top-level.
1569 ASSERT_TRUE(map.find(id) != map.end());
1570 ResourceProvider::ResourceId parent_id = map.find(id)->second;
1571 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1572 resource_ids_to_transfer.push_back(parent_id);
1573 resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1574 &sent_to_top_level);
1575 EXPECT_TRUE(resource_provider_->InUseByConsumer(parent_id));
1578 // Stop using resource.
1579 ResourceProvider::ResourceIdArray empty;
1580 resource_provider_->DeclareUsedResourcesFromChild(child_id, empty);
1581 // Resource is not yet returned to the child, since it's in use by the
1582 // top-level.
1583 EXPECT_TRUE(returned_to_child.empty());
1586 // Send the resource to the parent again.
1587 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1588 resource_ids_to_transfer.push_back(id);
1589 TransferableResourceArray list;
1590 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1591 &list);
1592 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id));
1593 resource_provider_->ReceiveFromChild(child_id, list);
1594 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1595 resource_ids_to_transfer);
1598 // Receive returns back from top-level.
1599 ReturnedResourceArray returned;
1600 TransferableResource::ReturnResources(sent_to_top_level, &returned);
1601 resource_provider_->ReceiveReturnsFromParent(returned);
1602 // Resource is still not yet returned to the child, since it's declared used
1603 // in the parent.
1604 EXPECT_TRUE(returned_to_child.empty());
1605 ASSERT_TRUE(map.find(id) != map.end());
1606 ResourceProvider::ResourceId parent_id = map.find(id)->second;
1607 EXPECT_FALSE(resource_provider_->InUseByConsumer(parent_id));
1610 sent_to_top_level.clear();
1611 // Parent transfers again to top-level.
1612 ASSERT_TRUE(map.find(id) != map.end());
1613 ResourceProvider::ResourceId parent_id = map.find(id)->second;
1614 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1615 resource_ids_to_transfer.push_back(parent_id);
1616 resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1617 &sent_to_top_level);
1618 EXPECT_TRUE(resource_provider_->InUseByConsumer(parent_id));
1621 // Receive returns back from top-level.
1622 ReturnedResourceArray returned;
1623 TransferableResource::ReturnResources(sent_to_top_level, &returned);
1624 resource_provider_->ReceiveReturnsFromParent(returned);
1625 // Resource is still not yet returned to the child, since it's still
1626 // declared used in the parent.
1627 EXPECT_TRUE(returned_to_child.empty());
1628 ASSERT_TRUE(map.find(id) != map.end());
1629 ResourceProvider::ResourceId parent_id = map.find(id)->second;
1630 EXPECT_FALSE(resource_provider_->InUseByConsumer(parent_id));
1633 // Stop using resource.
1634 ResourceProvider::ResourceIdArray empty;
1635 resource_provider_->DeclareUsedResourcesFromChild(child_id, empty);
1636 // Resource should have been returned to the child, since it's no longer in
1637 // use by the top-level.
1638 ASSERT_EQ(1u, returned_to_child.size());
1639 EXPECT_EQ(id, returned_to_child[0].id);
1640 EXPECT_EQ(2, returned_to_child[0].count);
1641 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
1642 returned_to_child.clear();
1643 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id));
1647 class ResourceProviderTestTextureFilters : public ResourceProviderTest {
1648 public:
1649 static void RunTest(GLenum child_filter, GLenum parent_filter) {
1650 scoped_ptr<TextureStateTrackingContext> child_context_owned(
1651 new TextureStateTrackingContext);
1652 TextureStateTrackingContext* child_context = child_context_owned.get();
1654 FakeOutputSurfaceClient child_output_surface_client;
1655 scoped_ptr<OutputSurface> child_output_surface(
1656 FakeOutputSurface::Create3d(child_context_owned.Pass()));
1657 CHECK(child_output_surface->BindToClient(&child_output_surface_client));
1658 scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
1659 new TestSharedBitmapManager());
1661 scoped_ptr<ResourceProvider> child_resource_provider(
1662 ResourceProvider::Create(child_output_surface.get(),
1663 shared_bitmap_manager.get(),
1664 NULL,
1665 NULL,
1667 false,
1668 1));
1670 scoped_ptr<TextureStateTrackingContext> parent_context_owned(
1671 new TextureStateTrackingContext);
1672 TextureStateTrackingContext* parent_context = parent_context_owned.get();
1674 FakeOutputSurfaceClient parent_output_surface_client;
1675 scoped_ptr<OutputSurface> parent_output_surface(
1676 FakeOutputSurface::Create3d(parent_context_owned.Pass()));
1677 CHECK(parent_output_surface->BindToClient(&parent_output_surface_client));
1679 scoped_ptr<ResourceProvider> parent_resource_provider(
1680 ResourceProvider::Create(parent_output_surface.get(),
1681 shared_bitmap_manager.get(),
1682 NULL,
1683 NULL,
1685 false,
1686 1));
1688 gfx::Size size(1, 1);
1689 ResourceFormat format = RGBA_8888;
1690 int child_texture_id = 1;
1691 int parent_texture_id = 2;
1693 size_t pixel_size = TextureSizeBytes(size, format);
1694 ASSERT_EQ(4U, pixel_size);
1696 ResourceProvider::ResourceId id = child_resource_provider->CreateResource(
1697 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE,
1698 format);
1700 // The new texture is created with GL_LINEAR.
1701 EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, child_texture_id))
1702 .Times(2); // Once to create and once to allocate.
1703 EXPECT_CALL(*child_context,
1704 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
1705 EXPECT_CALL(*child_context,
1706 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
1707 EXPECT_CALL(
1708 *child_context,
1709 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
1710 EXPECT_CALL(
1711 *child_context,
1712 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
1713 EXPECT_CALL(*child_context,
1714 texParameteri(GL_TEXTURE_2D,
1715 GL_TEXTURE_POOL_CHROMIUM,
1716 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM));
1717 child_resource_provider->AllocateForTesting(id);
1718 Mock::VerifyAndClearExpectations(child_context);
1720 uint8_t data[4] = { 1, 2, 3, 4 };
1722 EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, child_texture_id));
1723 child_resource_provider->CopyToResource(id, data, size);
1724 Mock::VerifyAndClearExpectations(child_context);
1726 // The texture is set to |child_filter| in the child.
1727 EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, child_texture_id));
1728 if (child_filter != GL_LINEAR) {
1729 EXPECT_CALL(
1730 *child_context,
1731 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, child_filter));
1732 EXPECT_CALL(
1733 *child_context,
1734 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, child_filter));
1736 SetResourceFilter(child_resource_provider.get(), id, child_filter);
1737 Mock::VerifyAndClearExpectations(child_context);
1739 ReturnedResourceArray returned_to_child;
1740 int child_id = parent_resource_provider->CreateChild(
1741 GetReturnCallback(&returned_to_child));
1743 // Transfer some resource to the parent.
1744 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1745 resource_ids_to_transfer.push_back(id);
1746 TransferableResourceArray list;
1748 EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, child_texture_id));
1749 EXPECT_CALL(*child_context,
1750 produceTextureCHROMIUM(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 bindTexture(GL_TEXTURE_2D, parent_texture_id));
1761 EXPECT_CALL(*parent_context, consumeTextureCHROMIUM(GL_TEXTURE_2D, _));
1762 parent_resource_provider->ReceiveFromChild(child_id, list);
1764 parent_resource_provider->WaitSyncPointIfNeeded(list[0].id);
1765 ResourceProvider::ScopedReadLockGL lock(parent_resource_provider.get(),
1766 list[0].id);
1768 Mock::VerifyAndClearExpectations(parent_context);
1770 parent_resource_provider->DeclareUsedResourcesFromChild(
1771 child_id, resource_ids_to_transfer);
1772 Mock::VerifyAndClearExpectations(parent_context);
1774 ResourceProvider::ResourceIdMap resource_map =
1775 parent_resource_provider->GetChildToParentMap(child_id);
1776 ResourceProvider::ResourceId mapped_id = resource_map[id];
1777 EXPECT_NE(0u, mapped_id);
1779 // The texture is set to |parent_filter| in the parent.
1780 EXPECT_CALL(*parent_context, bindTexture(GL_TEXTURE_2D, parent_texture_id));
1781 EXPECT_CALL(
1782 *parent_context,
1783 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, parent_filter));
1784 EXPECT_CALL(
1785 *parent_context,
1786 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, parent_filter));
1787 SetResourceFilter(parent_resource_provider.get(), mapped_id, parent_filter);
1788 Mock::VerifyAndClearExpectations(parent_context);
1790 // The texture should be reset to |child_filter| in the parent when it is
1791 // returned, since that is how it was received.
1792 EXPECT_CALL(*parent_context, bindTexture(GL_TEXTURE_2D, parent_texture_id));
1793 EXPECT_CALL(
1794 *parent_context,
1795 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, child_filter));
1796 EXPECT_CALL(
1797 *parent_context,
1798 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, child_filter));
1801 EXPECT_EQ(0u, returned_to_child.size());
1803 // Transfer resources back from the parent to the child. Set no resources
1804 // as being in use.
1805 ResourceProvider::ResourceIdArray no_resources;
1806 EXPECT_CALL(*parent_context, insertSyncPoint());
1807 parent_resource_provider->DeclareUsedResourcesFromChild(child_id,
1808 no_resources);
1809 Mock::VerifyAndClearExpectations(parent_context);
1811 ASSERT_EQ(1u, returned_to_child.size());
1812 child_resource_provider->ReceiveReturnsFromParent(returned_to_child);
1815 // The child remembers the texture filter is set to |child_filter|.
1816 EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, child_texture_id));
1817 SetResourceFilter(child_resource_provider.get(), id, child_filter);
1818 Mock::VerifyAndClearExpectations(child_context);
1822 TEST_P(ResourceProviderTest, TextureFilters_ChildNearestParentLinear) {
1823 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
1824 return;
1825 ResourceProviderTestTextureFilters::RunTest(GL_NEAREST, GL_LINEAR);
1828 TEST_P(ResourceProviderTest, TextureFilters_ChildLinearParentNearest) {
1829 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
1830 return;
1831 ResourceProviderTestTextureFilters::RunTest(GL_LINEAR, GL_NEAREST);
1834 TEST_P(ResourceProviderTest, TransferMailboxResources) {
1835 // Other mailbox transfers tested elsewhere.
1836 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
1837 return;
1838 unsigned texture = context()->createTexture();
1839 context()->bindTexture(GL_TEXTURE_2D, texture);
1840 uint8_t data[4] = { 1, 2, 3, 4 };
1841 context()->texImage2D(
1842 GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &data);
1843 gpu::Mailbox mailbox;
1844 context()->genMailboxCHROMIUM(mailbox.name);
1845 context()->produceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
1846 uint32 sync_point = context()->insertSyncPoint();
1848 // All the logic below assumes that the sync points are all positive.
1849 EXPECT_LT(0u, sync_point);
1851 uint32 release_sync_point = 0;
1852 bool lost_resource = false;
1853 BlockingTaskRunner* main_thread_task_runner = NULL;
1854 ReleaseCallbackImpl callback = base::Bind(ReleaseCallback,
1855 &release_sync_point,
1856 &lost_resource,
1857 &main_thread_task_runner);
1858 ResourceProvider::ResourceId resource =
1859 resource_provider_->CreateResourceFromTextureMailbox(
1860 TextureMailbox(mailbox, GL_TEXTURE_2D, sync_point),
1861 SingleReleaseCallbackImpl::Create(callback));
1862 EXPECT_EQ(1u, context()->NumTextures());
1863 EXPECT_EQ(0u, release_sync_point);
1865 // Transfer the resource, expect the sync points to be consistent.
1866 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1867 resource_ids_to_transfer.push_back(resource);
1868 TransferableResourceArray list;
1869 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
1870 ASSERT_EQ(1u, list.size());
1871 EXPECT_LE(sync_point, list[0].mailbox_holder.sync_point);
1872 EXPECT_EQ(0,
1873 memcmp(mailbox.name,
1874 list[0].mailbox_holder.mailbox.name,
1875 sizeof(mailbox.name)));
1876 EXPECT_EQ(0u, release_sync_point);
1878 context()->waitSyncPoint(list[0].mailbox_holder.sync_point);
1879 unsigned other_texture = context()->createTexture();
1880 context()->bindTexture(GL_TEXTURE_2D, other_texture);
1881 context()->consumeTextureCHROMIUM(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)));
1886 context()->produceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
1887 context()->deleteTexture(other_texture);
1888 list[0].mailbox_holder.sync_point = context()->insertSyncPoint();
1889 EXPECT_LT(0u, list[0].mailbox_holder.sync_point);
1891 // Receive the resource, then delete it, expect the sync points to be
1892 // consistent.
1893 ReturnedResourceArray returned;
1894 TransferableResource::ReturnResources(list, &returned);
1895 resource_provider_->ReceiveReturnsFromParent(returned);
1896 EXPECT_EQ(1u, context()->NumTextures());
1897 EXPECT_EQ(0u, release_sync_point);
1899 resource_provider_->DeleteResource(resource);
1900 EXPECT_LE(list[0].mailbox_holder.sync_point, release_sync_point);
1901 EXPECT_FALSE(lost_resource);
1902 EXPECT_EQ(main_thread_task_runner_.get(), main_thread_task_runner);
1905 // We're going to do the same thing as above, but testing the case where we
1906 // delete the resource before we receive it back.
1907 sync_point = release_sync_point;
1908 EXPECT_LT(0u, sync_point);
1909 release_sync_point = 0;
1910 resource = resource_provider_->CreateResourceFromTextureMailbox(
1911 TextureMailbox(mailbox, GL_TEXTURE_2D, sync_point),
1912 SingleReleaseCallbackImpl::Create(callback));
1913 EXPECT_EQ(1u, context()->NumTextures());
1914 EXPECT_EQ(0u, release_sync_point);
1916 // Transfer the resource, expect the sync points to be consistent.
1917 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1918 resource_ids_to_transfer.push_back(resource);
1919 TransferableResourceArray list;
1920 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
1921 ASSERT_EQ(1u, list.size());
1922 EXPECT_LE(sync_point, list[0].mailbox_holder.sync_point);
1923 EXPECT_EQ(0,
1924 memcmp(mailbox.name,
1925 list[0].mailbox_holder.mailbox.name,
1926 sizeof(mailbox.name)));
1927 EXPECT_EQ(0u, release_sync_point);
1929 context()->waitSyncPoint(list[0].mailbox_holder.sync_point);
1930 unsigned other_texture = context()->createTexture();
1931 context()->bindTexture(GL_TEXTURE_2D, other_texture);
1932 context()->consumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
1933 uint8_t test_data[4] = { 0 };
1934 context()->GetPixels(
1935 gfx::Size(1, 1), RGBA_8888, test_data);
1936 EXPECT_EQ(0, memcmp(data, test_data, sizeof(data)));
1937 context()->produceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
1938 context()->deleteTexture(other_texture);
1939 list[0].mailbox_holder.sync_point = context()->insertSyncPoint();
1940 EXPECT_LT(0u, list[0].mailbox_holder.sync_point);
1942 // Delete the resource, which shouldn't do anything.
1943 resource_provider_->DeleteResource(resource);
1944 EXPECT_EQ(1u, context()->NumTextures());
1945 EXPECT_EQ(0u, release_sync_point);
1947 // Then receive the resource which should release the mailbox, expect the
1948 // sync points to be consistent.
1949 ReturnedResourceArray returned;
1950 TransferableResource::ReturnResources(list, &returned);
1951 resource_provider_->ReceiveReturnsFromParent(returned);
1952 EXPECT_LE(list[0].mailbox_holder.sync_point, release_sync_point);
1953 EXPECT_FALSE(lost_resource);
1954 EXPECT_EQ(main_thread_task_runner_.get(), main_thread_task_runner);
1957 context()->waitSyncPoint(release_sync_point);
1958 context()->bindTexture(GL_TEXTURE_2D, texture);
1959 context()->consumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
1960 context()->deleteTexture(texture);
1963 TEST_P(ResourceProviderTest, LostResourceInParent) {
1964 gfx::Size size(1, 1);
1965 ResourceFormat format = RGBA_8888;
1966 ResourceProvider::ResourceId resource =
1967 child_resource_provider_->CreateResource(
1968 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE,
1969 format);
1970 child_resource_provider_->AllocateForTesting(resource);
1971 // Expect a GL resource to be lost.
1972 bool should_lose_resource =
1973 GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE;
1975 ReturnedResourceArray returned_to_child;
1976 int child_id =
1977 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1979 // Transfer the resource to the parent.
1980 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1981 resource_ids_to_transfer.push_back(resource);
1982 TransferableResourceArray list;
1983 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1984 &list);
1985 EXPECT_EQ(1u, list.size());
1987 resource_provider_->ReceiveFromChild(child_id, list);
1988 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1989 resource_ids_to_transfer);
1992 // Lose the output surface in the parent.
1993 resource_provider_->DidLoseOutputSurface();
1996 EXPECT_EQ(0u, returned_to_child.size());
1998 // Transfer resources back from the parent to the child. Set no resources as
1999 // being in use.
2000 ResourceProvider::ResourceIdArray no_resources;
2001 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
2003 // Expect a GL resource to be lost.
2004 ASSERT_EQ(1u, returned_to_child.size());
2005 EXPECT_EQ(should_lose_resource, returned_to_child[0].lost);
2006 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
2007 returned_to_child.clear();
2010 // A GL resource should be lost.
2011 EXPECT_EQ(should_lose_resource, child_resource_provider_->IsLost(resource));
2013 // Lost resources stay in use in the parent forever.
2014 EXPECT_EQ(should_lose_resource,
2015 child_resource_provider_->InUseByConsumer(resource));
2018 TEST_P(ResourceProviderTest, LostResourceInGrandParent) {
2019 gfx::Size size(1, 1);
2020 ResourceFormat format = RGBA_8888;
2021 ResourceProvider::ResourceId resource =
2022 child_resource_provider_->CreateResource(
2023 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE,
2024 format);
2025 child_resource_provider_->AllocateForTesting(resource);
2027 ReturnedResourceArray returned_to_child;
2028 int child_id =
2029 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
2031 // Transfer the resource to the parent.
2032 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2033 resource_ids_to_transfer.push_back(resource);
2034 TransferableResourceArray list;
2035 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
2036 &list);
2037 EXPECT_EQ(1u, list.size());
2039 resource_provider_->ReceiveFromChild(child_id, list);
2040 resource_provider_->DeclareUsedResourcesFromChild(child_id,
2041 resource_ids_to_transfer);
2045 ResourceProvider::ResourceIdMap resource_map =
2046 resource_provider_->GetChildToParentMap(child_id);
2047 ResourceProvider::ResourceId parent_resource = resource_map[resource];
2048 EXPECT_NE(0u, parent_resource);
2050 // Transfer to a grandparent.
2051 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2052 resource_ids_to_transfer.push_back(parent_resource);
2053 TransferableResourceArray list;
2054 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
2056 // Receive back a lost resource from the grandparent.
2057 EXPECT_EQ(1u, list.size());
2058 EXPECT_EQ(parent_resource, list[0].id);
2059 ReturnedResourceArray returned;
2060 TransferableResource::ReturnResources(list, &returned);
2061 EXPECT_EQ(1u, returned.size());
2062 EXPECT_EQ(parent_resource, returned[0].id);
2063 returned[0].lost = true;
2064 resource_provider_->ReceiveReturnsFromParent(returned);
2066 // The resource should be lost.
2067 EXPECT_TRUE(resource_provider_->IsLost(parent_resource));
2069 // Lost resources stay in use in the parent forever.
2070 EXPECT_TRUE(resource_provider_->InUseByConsumer(parent_resource));
2074 EXPECT_EQ(0u, returned_to_child.size());
2076 // Transfer resources back from the parent to the child. Set no resources as
2077 // being in use.
2078 ResourceProvider::ResourceIdArray no_resources;
2079 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
2081 // Expect the resource to be lost.
2082 ASSERT_EQ(1u, returned_to_child.size());
2083 EXPECT_TRUE(returned_to_child[0].lost);
2084 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
2085 returned_to_child.clear();
2088 // The resource should be lost.
2089 EXPECT_TRUE(child_resource_provider_->IsLost(resource));
2091 // Lost resources stay in use in the parent forever.
2092 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(resource));
2095 TEST_P(ResourceProviderTest, LostMailboxInParent) {
2096 uint32 release_sync_point = 0;
2097 bool lost_resource = false;
2098 bool release_called = false;
2099 uint32 sync_point = 0;
2100 ResourceProvider::ResourceId resource = CreateChildMailbox(
2101 &release_sync_point, &lost_resource, &release_called, &sync_point);
2103 ReturnedResourceArray returned_to_child;
2104 int child_id =
2105 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
2107 // Transfer the resource to the parent.
2108 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2109 resource_ids_to_transfer.push_back(resource);
2110 TransferableResourceArray list;
2111 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
2112 &list);
2113 EXPECT_EQ(1u, list.size());
2115 resource_provider_->ReceiveFromChild(child_id, list);
2116 resource_provider_->DeclareUsedResourcesFromChild(child_id,
2117 resource_ids_to_transfer);
2120 // Lose the output surface in the parent.
2121 resource_provider_->DidLoseOutputSurface();
2124 EXPECT_EQ(0u, returned_to_child.size());
2126 // Transfer resources back from the parent to the child. Set no resources as
2127 // being in use.
2128 ResourceProvider::ResourceIdArray no_resources;
2129 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
2131 ASSERT_EQ(1u, returned_to_child.size());
2132 // Losing an output surface only loses hardware resources.
2133 EXPECT_EQ(returned_to_child[0].lost,
2134 GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE);
2135 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
2136 returned_to_child.clear();
2139 // Delete the resource in the child. Expect the resource to be lost if it's
2140 // a GL texture.
2141 child_resource_provider_->DeleteResource(resource);
2142 EXPECT_EQ(lost_resource,
2143 GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE);
2146 TEST_P(ResourceProviderTest, LostMailboxInGrandParent) {
2147 uint32 release_sync_point = 0;
2148 bool lost_resource = false;
2149 bool release_called = false;
2150 uint32 sync_point = 0;
2151 ResourceProvider::ResourceId resource = CreateChildMailbox(
2152 &release_sync_point, &lost_resource, &release_called, &sync_point);
2154 ReturnedResourceArray returned_to_child;
2155 int child_id =
2156 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
2158 // Transfer the resource to the parent.
2159 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2160 resource_ids_to_transfer.push_back(resource);
2161 TransferableResourceArray list;
2162 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
2163 &list);
2164 EXPECT_EQ(1u, list.size());
2166 resource_provider_->ReceiveFromChild(child_id, list);
2167 resource_provider_->DeclareUsedResourcesFromChild(child_id,
2168 resource_ids_to_transfer);
2172 ResourceProvider::ResourceIdMap resource_map =
2173 resource_provider_->GetChildToParentMap(child_id);
2174 ResourceProvider::ResourceId parent_resource = resource_map[resource];
2175 EXPECT_NE(0u, parent_resource);
2177 // Transfer to a grandparent.
2178 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2179 resource_ids_to_transfer.push_back(parent_resource);
2180 TransferableResourceArray list;
2181 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
2183 // Receive back a lost resource from the grandparent.
2184 EXPECT_EQ(1u, list.size());
2185 EXPECT_EQ(parent_resource, list[0].id);
2186 ReturnedResourceArray returned;
2187 TransferableResource::ReturnResources(list, &returned);
2188 EXPECT_EQ(1u, returned.size());
2189 EXPECT_EQ(parent_resource, returned[0].id);
2190 returned[0].lost = true;
2191 resource_provider_->ReceiveReturnsFromParent(returned);
2195 EXPECT_EQ(0u, returned_to_child.size());
2197 // Transfer resources back from the parent to the child. Set no resources as
2198 // being in use.
2199 ResourceProvider::ResourceIdArray no_resources;
2200 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
2202 // Expect the resource to be lost.
2203 ASSERT_EQ(1u, returned_to_child.size());
2204 EXPECT_TRUE(returned_to_child[0].lost);
2205 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
2206 returned_to_child.clear();
2209 // Delete the resource in the child. Expect the resource to be lost.
2210 child_resource_provider_->DeleteResource(resource);
2211 EXPECT_TRUE(lost_resource);
2214 TEST_P(ResourceProviderTest, Shutdown) {
2215 uint32 release_sync_point = 0;
2216 bool lost_resource = false;
2217 bool release_called = false;
2218 uint32 sync_point = 0;
2219 CreateChildMailbox(
2220 &release_sync_point, &lost_resource, &release_called, &sync_point);
2222 EXPECT_EQ(0u, release_sync_point);
2223 EXPECT_FALSE(lost_resource);
2225 child_resource_provider_ = nullptr;
2227 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) {
2228 EXPECT_LE(sync_point, release_sync_point);
2230 EXPECT_TRUE(release_called);
2231 EXPECT_FALSE(lost_resource);
2234 TEST_P(ResourceProviderTest, ShutdownWithExportedResource) {
2235 uint32 release_sync_point = 0;
2236 bool lost_resource = false;
2237 bool release_called = false;
2238 uint32 sync_point = 0;
2239 ResourceProvider::ResourceId resource = CreateChildMailbox(
2240 &release_sync_point, &lost_resource, &release_called, &sync_point);
2242 // Transfer the resource, so we can't release it properly on shutdown.
2243 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2244 resource_ids_to_transfer.push_back(resource);
2245 TransferableResourceArray list;
2246 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
2247 &list);
2249 EXPECT_EQ(0u, release_sync_point);
2250 EXPECT_FALSE(lost_resource);
2252 child_resource_provider_ = nullptr;
2254 // Since the resource is in the parent, the child considers it lost.
2255 EXPECT_EQ(0u, release_sync_point);
2256 EXPECT_TRUE(lost_resource);
2259 TEST_P(ResourceProviderTest, LostContext) {
2260 // TextureMailbox callbacks only exist for GL textures for now.
2261 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
2262 return;
2263 unsigned texture = context()->createTexture();
2264 context()->bindTexture(GL_TEXTURE_2D, texture);
2265 gpu::Mailbox mailbox;
2266 context()->genMailboxCHROMIUM(mailbox.name);
2267 context()->produceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
2268 uint32 sync_point = context()->insertSyncPoint();
2270 EXPECT_LT(0u, sync_point);
2272 uint32 release_sync_point = 0;
2273 bool lost_resource = false;
2274 BlockingTaskRunner* main_thread_task_runner = NULL;
2275 scoped_ptr<SingleReleaseCallbackImpl> callback =
2276 SingleReleaseCallbackImpl::Create(base::Bind(ReleaseCallback,
2277 &release_sync_point,
2278 &lost_resource,
2279 &main_thread_task_runner));
2280 resource_provider_->CreateResourceFromTextureMailbox(
2281 TextureMailbox(mailbox, GL_TEXTURE_2D, sync_point), callback.Pass());
2283 EXPECT_EQ(0u, release_sync_point);
2284 EXPECT_FALSE(lost_resource);
2285 EXPECT_EQ(NULL, main_thread_task_runner);
2287 resource_provider_->DidLoseOutputSurface();
2288 resource_provider_ = nullptr;
2290 EXPECT_LE(sync_point, release_sync_point);
2291 EXPECT_TRUE(lost_resource);
2292 EXPECT_EQ(main_thread_task_runner_.get(), main_thread_task_runner);
2295 TEST_P(ResourceProviderTest, ScopedSampler) {
2296 // Sampling is only supported for GL textures.
2297 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
2298 return;
2300 scoped_ptr<TextureStateTrackingContext> context_owned(
2301 new TextureStateTrackingContext);
2302 TextureStateTrackingContext* context = context_owned.get();
2304 FakeOutputSurfaceClient output_surface_client;
2305 scoped_ptr<OutputSurface> output_surface(
2306 FakeOutputSurface::Create3d(context_owned.Pass()));
2307 CHECK(output_surface->BindToClient(&output_surface_client));
2309 scoped_ptr<ResourceProvider> resource_provider(
2310 ResourceProvider::Create(output_surface.get(),
2311 shared_bitmap_manager_.get(),
2312 gpu_memory_buffer_manager_.get(),
2313 NULL,
2315 false,
2316 1));
2318 gfx::Size size(1, 1);
2319 ResourceFormat format = RGBA_8888;
2320 int texture_id = 1;
2322 ResourceProvider::ResourceId id = resource_provider->CreateResource(
2323 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
2325 // Check that the texture gets created with the right sampler settings.
2326 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id))
2327 .Times(2); // Once to create and once to allocate.
2328 EXPECT_CALL(*context,
2329 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
2330 EXPECT_CALL(*context,
2331 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
2332 EXPECT_CALL(
2333 *context,
2334 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
2335 EXPECT_CALL(
2336 *context,
2337 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
2338 EXPECT_CALL(*context,
2339 texParameteri(GL_TEXTURE_2D,
2340 GL_TEXTURE_POOL_CHROMIUM,
2341 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM));
2343 resource_provider->AllocateForTesting(id);
2344 Mock::VerifyAndClearExpectations(context);
2346 // Creating a sampler with the default filter should not change any texture
2347 // parameters.
2349 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
2350 ResourceProvider::ScopedSamplerGL sampler(
2351 resource_provider.get(), id, GL_TEXTURE_2D, GL_LINEAR);
2352 Mock::VerifyAndClearExpectations(context);
2355 // Using a different filter should be reflected in the texture parameters.
2357 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
2358 EXPECT_CALL(
2359 *context,
2360 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
2361 EXPECT_CALL(
2362 *context,
2363 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
2364 ResourceProvider::ScopedSamplerGL sampler(
2365 resource_provider.get(), id, GL_TEXTURE_2D, GL_NEAREST);
2366 Mock::VerifyAndClearExpectations(context);
2369 // Test resetting to the default filter.
2371 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
2372 EXPECT_CALL(*context,
2373 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
2374 EXPECT_CALL(*context,
2375 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
2376 ResourceProvider::ScopedSamplerGL sampler(
2377 resource_provider.get(), id, GL_TEXTURE_2D, GL_LINEAR);
2378 Mock::VerifyAndClearExpectations(context);
2382 TEST_P(ResourceProviderTest, ManagedResource) {
2383 // Sampling is only supported for GL textures.
2384 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
2385 return;
2387 scoped_ptr<TextureStateTrackingContext> context_owned(
2388 new TextureStateTrackingContext);
2389 TextureStateTrackingContext* context = context_owned.get();
2391 FakeOutputSurfaceClient output_surface_client;
2392 scoped_ptr<OutputSurface> output_surface(
2393 FakeOutputSurface::Create3d(context_owned.Pass()));
2394 CHECK(output_surface->BindToClient(&output_surface_client));
2396 scoped_ptr<ResourceProvider> resource_provider(
2397 ResourceProvider::Create(output_surface.get(),
2398 shared_bitmap_manager_.get(),
2399 gpu_memory_buffer_manager_.get(),
2400 NULL,
2402 false,
2403 1));
2405 gfx::Size size(1, 1);
2406 ResourceFormat format = RGBA_8888;
2407 int texture_id = 1;
2409 // Check that the texture gets created with the right sampler settings.
2410 ResourceProvider::ResourceId id = resource_provider->CreateManagedResource(
2411 size, GL_TEXTURE_2D, GL_CLAMP_TO_EDGE,
2412 ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
2413 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
2414 EXPECT_CALL(*context,
2415 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
2416 EXPECT_CALL(*context,
2417 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
2418 EXPECT_CALL(
2419 *context,
2420 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
2421 EXPECT_CALL(
2422 *context,
2423 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
2424 EXPECT_CALL(*context,
2425 texParameteri(GL_TEXTURE_2D,
2426 GL_TEXTURE_POOL_CHROMIUM,
2427 GL_TEXTURE_POOL_MANAGED_CHROMIUM));
2428 resource_provider->CreateForTesting(id);
2429 EXPECT_NE(0u, id);
2431 Mock::VerifyAndClearExpectations(context);
2434 TEST_P(ResourceProviderTest, TextureWrapMode) {
2435 // Sampling is only supported for GL textures.
2436 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
2437 return;
2439 scoped_ptr<TextureStateTrackingContext> context_owned(
2440 new TextureStateTrackingContext);
2441 TextureStateTrackingContext* context = context_owned.get();
2443 FakeOutputSurfaceClient output_surface_client;
2444 scoped_ptr<OutputSurface> output_surface(
2445 FakeOutputSurface::Create3d(context_owned.Pass()));
2446 CHECK(output_surface->BindToClient(&output_surface_client));
2448 scoped_ptr<ResourceProvider> resource_provider(
2449 ResourceProvider::Create(output_surface.get(),
2450 shared_bitmap_manager_.get(),
2451 gpu_memory_buffer_manager_.get(),
2452 NULL,
2454 false,
2455 1));
2457 gfx::Size size(1, 1);
2458 ResourceFormat format = RGBA_8888;
2459 GLenum texture_pool = GL_TEXTURE_POOL_UNMANAGED_CHROMIUM;
2461 for (int texture_id = 1; texture_id <= 2; ++texture_id) {
2462 GLint wrap_mode = texture_id == 1 ? GL_CLAMP_TO_EDGE : GL_REPEAT;
2463 // Check that the texture gets created with the right sampler settings.
2464 ResourceProvider::ResourceId id = resource_provider->CreateGLTexture(
2465 size, GL_TEXTURE_2D, texture_pool, wrap_mode,
2466 ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
2467 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
2468 EXPECT_CALL(*context,
2469 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
2470 EXPECT_CALL(*context,
2471 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
2472 EXPECT_CALL(*context,
2473 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap_mode));
2474 EXPECT_CALL(*context,
2475 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap_mode));
2476 EXPECT_CALL(*context,
2477 texParameteri(GL_TEXTURE_2D,
2478 GL_TEXTURE_POOL_CHROMIUM,
2479 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM));
2480 resource_provider->CreateForTesting(id);
2481 EXPECT_NE(0u, id);
2483 Mock::VerifyAndClearExpectations(context);
2487 TEST_P(ResourceProviderTest, TextureHint) {
2488 // Sampling is only supported for GL textures.
2489 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
2490 return;
2492 scoped_ptr<TextureStateTrackingContext> context_owned(
2493 new TextureStateTrackingContext);
2494 TextureStateTrackingContext* context = context_owned.get();
2495 context->set_support_texture_storage(true);
2496 context->set_support_texture_usage(true);
2498 FakeOutputSurfaceClient output_surface_client;
2499 scoped_ptr<OutputSurface> output_surface(
2500 FakeOutputSurface::Create3d(context_owned.Pass()));
2501 CHECK(output_surface->BindToClient(&output_surface_client));
2503 scoped_ptr<ResourceProvider> resource_provider(
2504 ResourceProvider::Create(output_surface.get(),
2505 shared_bitmap_manager_.get(),
2506 gpu_memory_buffer_manager_.get(),
2507 NULL,
2509 false,
2510 1));
2512 gfx::Size size(1, 1);
2513 ResourceFormat format = RGBA_8888;
2514 GLenum texture_pool = GL_TEXTURE_POOL_UNMANAGED_CHROMIUM;
2516 const ResourceProvider::TextureHint hints[4] = {
2517 ResourceProvider::TEXTURE_HINT_DEFAULT,
2518 ResourceProvider::TEXTURE_HINT_IMMUTABLE,
2519 ResourceProvider::TEXTURE_HINT_FRAMEBUFFER,
2520 ResourceProvider::TEXTURE_HINT_IMMUTABLE_FRAMEBUFFER,
2522 for (GLuint texture_id = 1; texture_id <= arraysize(hints); ++texture_id) {
2523 // Check that the texture gets created with the right sampler settings.
2524 ResourceProvider::ResourceId id =
2525 resource_provider->CreateGLTexture(size,
2526 GL_TEXTURE_2D,
2527 texture_pool,
2528 GL_CLAMP_TO_EDGE,
2529 hints[texture_id - 1],
2530 format);
2531 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
2532 EXPECT_CALL(*context,
2533 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
2534 EXPECT_CALL(*context,
2535 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
2536 EXPECT_CALL(
2537 *context,
2538 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
2539 EXPECT_CALL(
2540 *context,
2541 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
2542 EXPECT_CALL(*context,
2543 texParameteri(GL_TEXTURE_2D,
2544 GL_TEXTURE_POOL_CHROMIUM,
2545 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM));
2546 // Check only TEXTURE_HINT_FRAMEBUFFER set GL_TEXTURE_USAGE_ANGLE.
2547 bool is_framebuffer_hint =
2548 hints[texture_id - 1] & ResourceProvider::TEXTURE_HINT_FRAMEBUFFER;
2549 EXPECT_CALL(*context,
2550 texParameteri(GL_TEXTURE_2D,
2551 GL_TEXTURE_USAGE_ANGLE,
2552 GL_FRAMEBUFFER_ATTACHMENT_ANGLE))
2553 .Times(is_framebuffer_hint ? 1 : 0);
2554 resource_provider->CreateForTesting(id);
2555 EXPECT_NE(0u, id);
2557 Mock::VerifyAndClearExpectations(context);
2561 TEST_P(ResourceProviderTest, TextureMailbox_SharedMemory) {
2562 if (GetParam() != ResourceProvider::RESOURCE_TYPE_BITMAP)
2563 return;
2565 gfx::Size size(64, 64);
2566 const uint32_t kBadBeef = 0xbadbeef;
2567 scoped_ptr<SharedBitmap> shared_bitmap(
2568 CreateAndFillSharedBitmap(shared_bitmap_manager_.get(), size, kBadBeef));
2570 FakeOutputSurfaceClient output_surface_client;
2571 scoped_ptr<OutputSurface> output_surface(
2572 FakeOutputSurface::CreateSoftware(make_scoped_ptr(
2573 new SoftwareOutputDevice)));
2574 CHECK(output_surface->BindToClient(&output_surface_client));
2576 scoped_ptr<ResourceProvider> resource_provider(
2577 ResourceProvider::Create(output_surface.get(),
2578 shared_bitmap_manager_.get(),
2579 gpu_memory_buffer_manager_.get(),
2580 main_thread_task_runner_.get(),
2582 false,
2583 1));
2585 uint32 release_sync_point = 0;
2586 bool lost_resource = false;
2587 BlockingTaskRunner* main_thread_task_runner = NULL;
2588 scoped_ptr<SingleReleaseCallbackImpl> callback =
2589 SingleReleaseCallbackImpl::Create(base::Bind(&ReleaseCallback,
2590 &release_sync_point,
2591 &lost_resource,
2592 &main_thread_task_runner));
2593 TextureMailbox mailbox(shared_bitmap.get(), size);
2595 ResourceProvider::ResourceId id =
2596 resource_provider->CreateResourceFromTextureMailbox(
2597 mailbox, callback.Pass());
2598 EXPECT_NE(0u, id);
2601 ResourceProvider::ScopedReadLockSoftware lock(resource_provider.get(), id);
2602 const SkBitmap* sk_bitmap = lock.sk_bitmap();
2603 EXPECT_EQ(sk_bitmap->width(), size.width());
2604 EXPECT_EQ(sk_bitmap->height(), size.height());
2605 EXPECT_EQ(*sk_bitmap->getAddr32(16, 16), kBadBeef);
2608 resource_provider->DeleteResource(id);
2609 EXPECT_EQ(0u, release_sync_point);
2610 EXPECT_FALSE(lost_resource);
2611 EXPECT_EQ(main_thread_task_runner_.get(), main_thread_task_runner);
2614 class ResourceProviderTestTextureMailboxGLFilters
2615 : public ResourceProviderTest {
2616 public:
2617 static void RunTest(TestSharedBitmapManager* shared_bitmap_manager,
2618 TestGpuMemoryBufferManager* gpu_memory_buffer_manager,
2619 BlockingTaskRunner* main_thread_task_runner,
2620 bool mailbox_nearest_neighbor,
2621 GLenum sampler_filter) {
2622 scoped_ptr<TextureStateTrackingContext> context_owned(
2623 new TextureStateTrackingContext);
2624 TextureStateTrackingContext* context = context_owned.get();
2626 FakeOutputSurfaceClient output_surface_client;
2627 scoped_ptr<OutputSurface> output_surface(
2628 FakeOutputSurface::Create3d(context_owned.Pass()));
2629 CHECK(output_surface->BindToClient(&output_surface_client));
2631 scoped_ptr<ResourceProvider> resource_provider(
2632 ResourceProvider::Create(output_surface.get(),
2633 shared_bitmap_manager,
2634 gpu_memory_buffer_manager,
2635 main_thread_task_runner,
2637 false,
2638 1));
2640 unsigned texture_id = 1;
2641 uint32 sync_point = 30;
2642 unsigned target = GL_TEXTURE_2D;
2644 EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
2645 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
2646 EXPECT_CALL(*context, insertSyncPoint()).Times(0);
2647 EXPECT_CALL(*context, produceTextureCHROMIUM(_, _)).Times(0);
2648 EXPECT_CALL(*context, consumeTextureCHROMIUM(_, _)).Times(0);
2650 gpu::Mailbox gpu_mailbox;
2651 memcpy(gpu_mailbox.name, "Hello world", strlen("Hello world") + 1);
2652 uint32 release_sync_point = 0;
2653 bool lost_resource = false;
2654 BlockingTaskRunner* mailbox_task_runner = NULL;
2655 scoped_ptr<SingleReleaseCallbackImpl> callback =
2656 SingleReleaseCallbackImpl::Create(base::Bind(&ReleaseCallback,
2657 &release_sync_point,
2658 &lost_resource,
2659 &mailbox_task_runner));
2661 TextureMailbox mailbox(gpu_mailbox, target, sync_point);
2662 mailbox.set_nearest_neighbor(mailbox_nearest_neighbor);
2664 ResourceProvider::ResourceId id =
2665 resource_provider->CreateResourceFromTextureMailbox(mailbox,
2666 callback.Pass());
2667 EXPECT_NE(0u, id);
2669 Mock::VerifyAndClearExpectations(context);
2672 // Mailbox sync point WaitSyncPoint before using the texture.
2673 EXPECT_CALL(*context, waitSyncPoint(sync_point));
2674 resource_provider->WaitSyncPointIfNeeded(id);
2675 Mock::VerifyAndClearExpectations(context);
2677 // Using the texture does a consume of the mailbox.
2678 EXPECT_CALL(*context, bindTexture(target, texture_id)).Times(2);
2679 EXPECT_CALL(*context, consumeTextureCHROMIUM(target, _));
2681 EXPECT_CALL(*context, insertSyncPoint()).Times(0);
2682 EXPECT_CALL(*context, produceTextureCHROMIUM(_, _)).Times(0);
2684 // The sampler will reset these if |mailbox_nearest_neighbor| does not
2685 // match |sampler_filter|.
2686 if (mailbox_nearest_neighbor != (sampler_filter == GL_NEAREST)) {
2687 EXPECT_CALL(*context, texParameteri(
2688 GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, sampler_filter));
2689 EXPECT_CALL(*context, texParameteri(
2690 GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, sampler_filter));
2693 ResourceProvider::ScopedSamplerGL lock(
2694 resource_provider.get(), id, sampler_filter);
2695 Mock::VerifyAndClearExpectations(context);
2697 // When done with it, a sync point should be inserted, but no produce is
2698 // necessary.
2699 EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
2700 EXPECT_CALL(*context, insertSyncPoint());
2701 EXPECT_CALL(*context, produceTextureCHROMIUM(_, _)).Times(0);
2703 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
2704 EXPECT_CALL(*context, consumeTextureCHROMIUM(_, _)).Times(0);
2707 resource_provider->DeleteResource(id);
2708 EXPECT_EQ(0u, release_sync_point);
2709 EXPECT_FALSE(lost_resource);
2710 EXPECT_EQ(main_thread_task_runner, mailbox_task_runner);
2714 TEST_P(ResourceProviderTest, TextureMailbox_GLTexture2D_LinearToLinear) {
2715 // Mailboxing is only supported for GL textures.
2716 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
2717 return;
2719 ResourceProviderTestTextureMailboxGLFilters::RunTest(
2720 shared_bitmap_manager_.get(),
2721 gpu_memory_buffer_manager_.get(),
2722 main_thread_task_runner_.get(),
2723 false,
2724 GL_LINEAR);
2727 TEST_P(ResourceProviderTest, TextureMailbox_GLTexture2D_NearestToNearest) {
2728 // Mailboxing is only supported for GL textures.
2729 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
2730 return;
2732 ResourceProviderTestTextureMailboxGLFilters::RunTest(
2733 shared_bitmap_manager_.get(),
2734 gpu_memory_buffer_manager_.get(),
2735 main_thread_task_runner_.get(),
2736 true,
2737 GL_NEAREST);
2740 TEST_P(ResourceProviderTest, TextureMailbox_GLTexture2D_NearestToLinear) {
2741 // Mailboxing is only supported for GL textures.
2742 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
2743 return;
2745 ResourceProviderTestTextureMailboxGLFilters::RunTest(
2746 shared_bitmap_manager_.get(),
2747 gpu_memory_buffer_manager_.get(),
2748 main_thread_task_runner_.get(),
2749 true,
2750 GL_LINEAR);
2753 TEST_P(ResourceProviderTest, TextureMailbox_GLTexture2D_LinearToNearest) {
2754 // Mailboxing is only supported for GL textures.
2755 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
2756 return;
2758 ResourceProviderTestTextureMailboxGLFilters::RunTest(
2759 shared_bitmap_manager_.get(),
2760 gpu_memory_buffer_manager_.get(),
2761 main_thread_task_runner_.get(),
2762 false,
2763 GL_NEAREST);
2766 TEST_P(ResourceProviderTest, TextureMailbox_GLTextureExternalOES) {
2767 // Mailboxing is only supported for GL textures.
2768 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
2769 return;
2771 scoped_ptr<TextureStateTrackingContext> context_owned(
2772 new TextureStateTrackingContext);
2773 TextureStateTrackingContext* context = context_owned.get();
2775 FakeOutputSurfaceClient output_surface_client;
2776 scoped_ptr<OutputSurface> output_surface(
2777 FakeOutputSurface::Create3d(context_owned.Pass()));
2778 CHECK(output_surface->BindToClient(&output_surface_client));
2780 scoped_ptr<ResourceProvider> resource_provider(
2781 ResourceProvider::Create(output_surface.get(),
2782 shared_bitmap_manager_.get(),
2783 gpu_memory_buffer_manager_.get(),
2784 NULL,
2786 false,
2787 1));
2789 unsigned texture_id = 1;
2790 uint32 sync_point = 30;
2791 unsigned target = GL_TEXTURE_EXTERNAL_OES;
2793 EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
2794 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
2795 EXPECT_CALL(*context, insertSyncPoint()).Times(0);
2796 EXPECT_CALL(*context, produceTextureCHROMIUM(_, _)).Times(0);
2797 EXPECT_CALL(*context, consumeTextureCHROMIUM(_, _)).Times(0);
2799 gpu::Mailbox gpu_mailbox;
2800 memcpy(gpu_mailbox.name, "Hello world", strlen("Hello world") + 1);
2801 scoped_ptr<SingleReleaseCallbackImpl> callback =
2802 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback));
2804 TextureMailbox mailbox(gpu_mailbox, target, sync_point);
2806 ResourceProvider::ResourceId id =
2807 resource_provider->CreateResourceFromTextureMailbox(
2808 mailbox, callback.Pass());
2809 EXPECT_NE(0u, id);
2811 Mock::VerifyAndClearExpectations(context);
2814 // Mailbox sync point WaitSyncPoint before using the texture.
2815 EXPECT_CALL(*context, waitSyncPoint(sync_point));
2816 resource_provider->WaitSyncPointIfNeeded(id);
2817 Mock::VerifyAndClearExpectations(context);
2819 // Using the texture does a consume of the mailbox.
2820 EXPECT_CALL(*context, bindTexture(target, texture_id));
2821 EXPECT_CALL(*context, consumeTextureCHROMIUM(target, _));
2823 EXPECT_CALL(*context, insertSyncPoint()).Times(0);
2824 EXPECT_CALL(*context, produceTextureCHROMIUM(_, _)).Times(0);
2826 ResourceProvider::ScopedReadLockGL lock(resource_provider.get(), id);
2827 Mock::VerifyAndClearExpectations(context);
2829 // When done with it, a sync point should be inserted, but no produce is
2830 // necessary.
2831 EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
2832 EXPECT_CALL(*context, insertSyncPoint());
2833 EXPECT_CALL(*context, produceTextureCHROMIUM(_, _)).Times(0);
2835 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
2836 EXPECT_CALL(*context, consumeTextureCHROMIUM(_, _)).Times(0);
2840 TEST_P(ResourceProviderTest,
2841 TextureMailbox_WaitSyncPointIfNeeded_WithSyncPoint) {
2842 // Mailboxing is only supported for GL textures.
2843 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
2844 return;
2846 scoped_ptr<TextureStateTrackingContext> context_owned(
2847 new TextureStateTrackingContext);
2848 TextureStateTrackingContext* context = context_owned.get();
2850 FakeOutputSurfaceClient output_surface_client;
2851 scoped_ptr<OutputSurface> output_surface(
2852 FakeOutputSurface::Create3d(context_owned.Pass()));
2853 CHECK(output_surface->BindToClient(&output_surface_client));
2855 scoped_ptr<ResourceProvider> resource_provider(
2856 ResourceProvider::Create(output_surface.get(),
2857 shared_bitmap_manager_.get(),
2858 gpu_memory_buffer_manager_.get(),
2859 NULL,
2861 false,
2862 1));
2864 uint32 sync_point = 30;
2865 unsigned target = GL_TEXTURE_2D;
2867 EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
2868 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
2869 EXPECT_CALL(*context, insertSyncPoint()).Times(0);
2870 EXPECT_CALL(*context, produceTextureCHROMIUM(_, _)).Times(0);
2871 EXPECT_CALL(*context, consumeTextureCHROMIUM(_, _)).Times(0);
2873 gpu::Mailbox gpu_mailbox;
2874 memcpy(gpu_mailbox.name, "Hello world", strlen("Hello world") + 1);
2875 scoped_ptr<SingleReleaseCallbackImpl> callback =
2876 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback));
2878 TextureMailbox mailbox(gpu_mailbox, target, sync_point);
2880 ResourceProvider::ResourceId id =
2881 resource_provider->CreateResourceFromTextureMailbox(mailbox,
2882 callback.Pass());
2883 EXPECT_NE(0u, id);
2885 Mock::VerifyAndClearExpectations(context);
2888 // First call to WaitSyncPointIfNeeded should call waitSyncPoint.
2889 EXPECT_CALL(*context, waitSyncPoint(sync_point));
2890 resource_provider->WaitSyncPointIfNeeded(id);
2891 Mock::VerifyAndClearExpectations(context);
2893 // Subsequent calls to WaitSyncPointIfNeeded shouldn't call waitSyncPoint.
2894 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
2895 resource_provider->WaitSyncPointIfNeeded(id);
2896 Mock::VerifyAndClearExpectations(context);
2900 TEST_P(ResourceProviderTest, TextureMailbox_WaitSyncPointIfNeeded_NoSyncPoint) {
2901 // Mailboxing is only supported for GL textures.
2902 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
2903 return;
2905 scoped_ptr<TextureStateTrackingContext> context_owned(
2906 new TextureStateTrackingContext);
2907 TextureStateTrackingContext* context = context_owned.get();
2909 FakeOutputSurfaceClient output_surface_client;
2910 scoped_ptr<OutputSurface> output_surface(
2911 FakeOutputSurface::Create3d(context_owned.Pass()));
2912 CHECK(output_surface->BindToClient(&output_surface_client));
2914 scoped_ptr<ResourceProvider> resource_provider(
2915 ResourceProvider::Create(output_surface.get(),
2916 shared_bitmap_manager_.get(),
2917 gpu_memory_buffer_manager_.get(),
2918 NULL,
2920 false,
2921 1));
2923 uint32 sync_point = 0;
2924 unsigned target = GL_TEXTURE_2D;
2926 EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
2927 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
2928 EXPECT_CALL(*context, insertSyncPoint()).Times(0);
2929 EXPECT_CALL(*context, produceTextureCHROMIUM(_, _)).Times(0);
2930 EXPECT_CALL(*context, consumeTextureCHROMIUM(_, _)).Times(0);
2932 gpu::Mailbox gpu_mailbox;
2933 memcpy(gpu_mailbox.name, "Hello world", strlen("Hello world") + 1);
2934 scoped_ptr<SingleReleaseCallbackImpl> callback =
2935 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback));
2937 TextureMailbox mailbox(gpu_mailbox, target, sync_point);
2939 ResourceProvider::ResourceId id =
2940 resource_provider->CreateResourceFromTextureMailbox(mailbox,
2941 callback.Pass());
2942 EXPECT_NE(0u, id);
2944 Mock::VerifyAndClearExpectations(context);
2947 // WaitSyncPointIfNeeded with sync_point == 0 shouldn't call waitSyncPoint.
2948 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
2949 resource_provider->WaitSyncPointIfNeeded(id);
2950 Mock::VerifyAndClearExpectations(context);
2954 class AllocationTrackingContext3D : public TestWebGraphicsContext3D {
2955 public:
2956 MOCK_METHOD0(NextTextureId, GLuint());
2957 MOCK_METHOD1(RetireTextureId, void(GLuint id));
2958 MOCK_METHOD2(bindTexture, void(GLenum target, GLuint texture));
2959 MOCK_METHOD5(texStorage2DEXT,
2960 void(GLenum target,
2961 GLint levels,
2962 GLuint internalformat,
2963 GLint width,
2964 GLint height));
2965 MOCK_METHOD9(texImage2D,
2966 void(GLenum target,
2967 GLint level,
2968 GLenum internalformat,
2969 GLsizei width,
2970 GLsizei height,
2971 GLint border,
2972 GLenum format,
2973 GLenum type,
2974 const void* pixels));
2975 MOCK_METHOD9(texSubImage2D,
2976 void(GLenum target,
2977 GLint level,
2978 GLint xoffset,
2979 GLint yoffset,
2980 GLsizei width,
2981 GLsizei height,
2982 GLenum format,
2983 GLenum type,
2984 const void* pixels));
2985 MOCK_METHOD9(asyncTexImage2DCHROMIUM,
2986 void(GLenum target,
2987 GLint level,
2988 GLenum internalformat,
2989 GLsizei width,
2990 GLsizei height,
2991 GLint border,
2992 GLenum format,
2993 GLenum type,
2994 const void* pixels));
2995 MOCK_METHOD9(asyncTexSubImage2DCHROMIUM,
2996 void(GLenum target,
2997 GLint level,
2998 GLint xoffset,
2999 GLint yoffset,
3000 GLsizei width,
3001 GLsizei height,
3002 GLenum format,
3003 GLenum type,
3004 const void* pixels));
3005 MOCK_METHOD8(compressedTexImage2D,
3006 void(GLenum target,
3007 GLint level,
3008 GLenum internalformat,
3009 GLsizei width,
3010 GLsizei height,
3011 GLint border,
3012 GLsizei image_size,
3013 const void* data));
3014 MOCK_METHOD1(waitAsyncTexImage2DCHROMIUM, void(GLenum));
3015 MOCK_METHOD4(createImageCHROMIUM,
3016 GLuint(ClientBuffer, GLsizei, GLsizei, GLenum));
3017 MOCK_METHOD1(destroyImageCHROMIUM, void(GLuint));
3018 MOCK_METHOD2(bindTexImage2DCHROMIUM, void(GLenum, GLint));
3019 MOCK_METHOD2(releaseTexImage2DCHROMIUM, void(GLenum, GLint));
3021 // We're mocking bindTexture, so we override
3022 // TestWebGraphicsContext3D::texParameteri to avoid assertions related to the
3023 // currently bound texture.
3024 virtual void texParameteri(GLenum target, GLenum pname, GLint param) {}
3027 TEST_P(ResourceProviderTest, TextureAllocation) {
3028 // Only for GL textures.
3029 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
3030 return;
3031 scoped_ptr<AllocationTrackingContext3D> context_owned(
3032 new StrictMock<AllocationTrackingContext3D>);
3033 AllocationTrackingContext3D* context = context_owned.get();
3035 FakeOutputSurfaceClient output_surface_client;
3036 scoped_ptr<OutputSurface> output_surface(
3037 FakeOutputSurface::Create3d(context_owned.Pass()));
3038 CHECK(output_surface->BindToClient(&output_surface_client));
3040 scoped_ptr<ResourceProvider> resource_provider(
3041 ResourceProvider::Create(output_surface.get(),
3042 shared_bitmap_manager_.get(),
3043 gpu_memory_buffer_manager_.get(),
3044 NULL,
3046 false,
3047 1));
3049 gfx::Size size(2, 2);
3050 gfx::Vector2d offset(0, 0);
3051 ResourceFormat format = RGBA_8888;
3052 ResourceProvider::ResourceId id = 0;
3053 uint8_t pixels[16] = { 0 };
3054 int texture_id = 123;
3056 // Lazy allocation. Don't allocate when creating the resource.
3057 id = resource_provider->CreateResource(
3058 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
3060 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3061 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(1);
3062 resource_provider->CreateForTesting(id);
3064 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3065 resource_provider->DeleteResource(id);
3067 Mock::VerifyAndClearExpectations(context);
3069 // Do allocate when we set the pixels.
3070 id = resource_provider->CreateResource(
3071 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
3073 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3074 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(3);
3075 EXPECT_CALL(*context, texImage2D(_, _, _, 2, 2, _, _, _, _)).Times(1);
3076 EXPECT_CALL(*context, texSubImage2D(_, _, _, _, 2, 2, _, _, _)).Times(1);
3077 resource_provider->CopyToResource(id, pixels, size);
3079 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3080 resource_provider->DeleteResource(id);
3082 Mock::VerifyAndClearExpectations(context);
3084 // Same for async version.
3085 id = resource_provider->CreateResource(
3086 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
3087 resource_provider->AcquirePixelBuffer(id);
3089 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3090 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
3091 EXPECT_CALL(*context, asyncTexImage2DCHROMIUM(_, _, _, 2, 2, _, _, _, _))
3092 .Times(1);
3093 resource_provider->BeginSetPixels(id);
3094 ASSERT_TRUE(resource_provider->DidSetPixelsComplete(id));
3096 resource_provider->ReleasePixelBuffer(id);
3098 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3099 resource_provider->DeleteResource(id);
3101 Mock::VerifyAndClearExpectations(context);
3104 TEST_P(ResourceProviderTest, TextureAllocationHint) {
3105 // Only for GL textures.
3106 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
3107 return;
3108 scoped_ptr<AllocationTrackingContext3D> context_owned(
3109 new StrictMock<AllocationTrackingContext3D>);
3110 AllocationTrackingContext3D* context = context_owned.get();
3111 context->set_support_texture_storage(true);
3112 context->set_support_texture_usage(true);
3114 FakeOutputSurfaceClient output_surface_client;
3115 scoped_ptr<OutputSurface> output_surface(
3116 FakeOutputSurface::Create3d(context_owned.Pass()));
3117 CHECK(output_surface->BindToClient(&output_surface_client));
3119 scoped_ptr<ResourceProvider> resource_provider(
3120 ResourceProvider::Create(output_surface.get(),
3121 shared_bitmap_manager_.get(),
3122 gpu_memory_buffer_manager_.get(),
3123 NULL,
3125 false,
3126 1));
3128 gfx::Size size(2, 2);
3130 const ResourceFormat formats[2] = {RGBA_8888, BGRA_8888};
3131 const ResourceProvider::TextureHint hints[4] = {
3132 ResourceProvider::TEXTURE_HINT_DEFAULT,
3133 ResourceProvider::TEXTURE_HINT_IMMUTABLE,
3134 ResourceProvider::TEXTURE_HINT_FRAMEBUFFER,
3135 ResourceProvider::TEXTURE_HINT_IMMUTABLE_FRAMEBUFFER,
3137 for (size_t i = 0; i < arraysize(formats); ++i) {
3138 for (GLuint texture_id = 1; texture_id <= arraysize(hints); ++texture_id) {
3139 // Lazy allocation. Don't allocate when creating the resource.
3140 ResourceProvider::ResourceId id = resource_provider->CreateResource(
3141 size, GL_CLAMP_TO_EDGE, hints[texture_id - 1], formats[i]);
3143 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3144 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
3145 bool is_immutable_hint =
3146 hints[texture_id - 1] & ResourceProvider::TEXTURE_HINT_IMMUTABLE;
3147 bool support_immutable_texture =
3148 is_immutable_hint && formats[i] == RGBA_8888;
3149 EXPECT_CALL(*context, texStorage2DEXT(_, _, _, 2, 2))
3150 .Times(support_immutable_texture ? 1 : 0);
3151 EXPECT_CALL(*context, texImage2D(_, _, _, 2, 2, _, _, _, _))
3152 .Times(support_immutable_texture ? 0 : 1);
3153 resource_provider->AllocateForTesting(id);
3155 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3156 resource_provider->DeleteResource(id);
3158 Mock::VerifyAndClearExpectations(context);
3163 TEST_P(ResourceProviderTest, TextureAllocationHint_BGRA) {
3164 // Only for GL textures.
3165 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
3166 return;
3167 scoped_ptr<AllocationTrackingContext3D> context_owned(
3168 new StrictMock<AllocationTrackingContext3D>);
3169 AllocationTrackingContext3D* context = context_owned.get();
3170 context->set_support_texture_format_bgra8888(true);
3171 context->set_support_texture_storage(true);
3172 context->set_support_texture_usage(true);
3174 FakeOutputSurfaceClient output_surface_client;
3175 scoped_ptr<OutputSurface> output_surface(
3176 FakeOutputSurface::Create3d(context_owned.Pass()));
3177 CHECK(output_surface->BindToClient(&output_surface_client));
3179 scoped_ptr<ResourceProvider> resource_provider(
3180 ResourceProvider::Create(output_surface.get(),
3181 shared_bitmap_manager_.get(),
3182 gpu_memory_buffer_manager_.get(),
3183 NULL,
3185 false,
3186 1));
3188 gfx::Size size(2, 2);
3189 const ResourceFormat formats[2] = {RGBA_8888, BGRA_8888};
3191 const ResourceProvider::TextureHint hints[4] = {
3192 ResourceProvider::TEXTURE_HINT_DEFAULT,
3193 ResourceProvider::TEXTURE_HINT_IMMUTABLE,
3194 ResourceProvider::TEXTURE_HINT_FRAMEBUFFER,
3195 ResourceProvider::TEXTURE_HINT_IMMUTABLE_FRAMEBUFFER,
3197 for (size_t i = 0; i < arraysize(formats); ++i) {
3198 for (GLuint texture_id = 1; texture_id <= arraysize(hints); ++texture_id) {
3199 // Lazy allocation. Don't allocate when creating the resource.
3200 ResourceProvider::ResourceId id = resource_provider->CreateResource(
3201 size, GL_CLAMP_TO_EDGE, hints[texture_id - 1], formats[i]);
3203 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3204 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
3205 bool is_immutable_hint =
3206 hints[texture_id - 1] & ResourceProvider::TEXTURE_HINT_IMMUTABLE;
3207 EXPECT_CALL(*context, texStorage2DEXT(_, _, _, 2, 2))
3208 .Times(is_immutable_hint ? 1 : 0);
3209 EXPECT_CALL(*context, texImage2D(_, _, _, 2, 2, _, _, _, _))
3210 .Times(is_immutable_hint ? 0 : 1);
3211 resource_provider->AllocateForTesting(id);
3213 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3214 resource_provider->DeleteResource(id);
3216 Mock::VerifyAndClearExpectations(context);
3221 TEST_P(ResourceProviderTest, PixelBuffer_GLTexture) {
3222 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
3223 return;
3224 scoped_ptr<AllocationTrackingContext3D> context_owned(
3225 new StrictMock<AllocationTrackingContext3D>);
3226 AllocationTrackingContext3D* context = context_owned.get();
3228 FakeOutputSurfaceClient output_surface_client;
3229 scoped_ptr<OutputSurface> output_surface(
3230 FakeOutputSurface::Create3d(context_owned.Pass()));
3231 CHECK(output_surface->BindToClient(&output_surface_client));
3233 gfx::Size size(2, 2);
3234 ResourceFormat format = RGBA_8888;
3235 ResourceProvider::ResourceId id = 0;
3236 int texture_id = 123;
3238 scoped_ptr<ResourceProvider> resource_provider(
3239 ResourceProvider::Create(output_surface.get(),
3240 shared_bitmap_manager_.get(),
3241 gpu_memory_buffer_manager_.get(),
3242 NULL,
3244 false,
3245 1));
3247 id = resource_provider->CreateResource(
3248 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
3249 resource_provider->AcquirePixelBuffer(id);
3251 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3252 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
3253 EXPECT_CALL(*context, asyncTexImage2DCHROMIUM(_, _, _, 2, 2, _, _, _, _))
3254 .Times(1);
3255 resource_provider->BeginSetPixels(id);
3257 EXPECT_TRUE(resource_provider->DidSetPixelsComplete(id));
3259 resource_provider->ReleasePixelBuffer(id);
3261 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3262 resource_provider->DeleteResource(id);
3264 Mock::VerifyAndClearExpectations(context);
3267 TEST_P(ResourceProviderTest, ForcingAsyncUploadToComplete) {
3268 // Only for GL textures.
3269 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
3270 return;
3271 scoped_ptr<AllocationTrackingContext3D> context_owned(
3272 new StrictMock<AllocationTrackingContext3D>);
3273 AllocationTrackingContext3D* context = context_owned.get();
3275 FakeOutputSurfaceClient output_surface_client;
3276 scoped_ptr<OutputSurface> output_surface(
3277 FakeOutputSurface::Create3d(context_owned.Pass()));
3278 CHECK(output_surface->BindToClient(&output_surface_client));
3280 gfx::Size size(2, 2);
3281 ResourceFormat format = RGBA_8888;
3282 ResourceProvider::ResourceId id = 0;
3283 int texture_id = 123;
3285 scoped_ptr<ResourceProvider> resource_provider(
3286 ResourceProvider::Create(output_surface.get(),
3287 shared_bitmap_manager_.get(),
3288 gpu_memory_buffer_manager_.get(),
3289 NULL,
3291 false,
3292 1));
3294 id = resource_provider->CreateResource(
3295 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
3296 resource_provider->AcquirePixelBuffer(id);
3298 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3299 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
3300 EXPECT_CALL(*context, asyncTexImage2DCHROMIUM(_, _, _, 2, 2, _, _, _, _))
3301 .Times(1);
3302 resource_provider->BeginSetPixels(id);
3304 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(1);
3305 EXPECT_CALL(*context, waitAsyncTexImage2DCHROMIUM(GL_TEXTURE_2D)).Times(1);
3306 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, 0)).Times(1);
3307 resource_provider->ForceSetPixelsToComplete(id);
3309 resource_provider->ReleasePixelBuffer(id);
3311 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3312 resource_provider->DeleteResource(id);
3314 Mock::VerifyAndClearExpectations(context);
3317 TEST_P(ResourceProviderTest, PixelBufferLostContext) {
3318 scoped_ptr<AllocationTrackingContext3D> context_owned(
3319 new NiceMock<AllocationTrackingContext3D>);
3320 AllocationTrackingContext3D* context = context_owned.get();
3322 FakeOutputSurfaceClient output_surface_client;
3323 scoped_ptr<OutputSurface> output_surface(
3324 FakeOutputSurface::Create3d(context_owned.Pass()));
3325 CHECK(output_surface->BindToClient(&output_surface_client));
3327 gfx::Size size(2, 2);
3328 ResourceFormat format = RGBA_8888;
3329 ResourceProvider::ResourceId id = 0;
3330 int texture_id = 123;
3332 scoped_ptr<ResourceProvider> resource_provider(
3333 ResourceProvider::Create(output_surface.get(),
3334 shared_bitmap_manager_.get(),
3335 gpu_memory_buffer_manager_.get(),
3336 NULL,
3338 false,
3339 1));
3341 EXPECT_CALL(*context, NextTextureId()).WillRepeatedly(Return(texture_id));
3343 id = resource_provider->CreateResource(
3344 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
3345 context->loseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB,
3346 GL_INNOCENT_CONTEXT_RESET_ARB);
3348 resource_provider->AcquirePixelBuffer(id);
3349 int stride;
3350 void* buffer = resource_provider->MapPixelBuffer(id, &stride);
3351 EXPECT_FALSE(buffer);
3352 resource_provider->UnmapPixelBuffer(id);
3353 Mock::VerifyAndClearExpectations(context);
3356 TEST_P(ResourceProviderTest, Image_GLTexture) {
3357 // Only for GL textures.
3358 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
3359 return;
3360 scoped_ptr<AllocationTrackingContext3D> context_owned(
3361 new StrictMock<AllocationTrackingContext3D>);
3362 AllocationTrackingContext3D* context = context_owned.get();
3364 FakeOutputSurfaceClient output_surface_client;
3365 scoped_ptr<OutputSurface> output_surface(
3366 FakeOutputSurface::Create3d(context_owned.Pass()));
3367 CHECK(output_surface->BindToClient(&output_surface_client));
3369 const int kWidth = 2;
3370 const int kHeight = 2;
3371 gfx::Size size(kWidth, kHeight);
3372 ResourceFormat format = RGBA_8888;
3373 ResourceProvider::ResourceId id = 0;
3374 const unsigned kTextureId = 123u;
3375 const unsigned kImageId = 234u;
3377 scoped_ptr<ResourceProvider> resource_provider(
3378 ResourceProvider::Create(output_surface.get(),
3379 shared_bitmap_manager_.get(),
3380 gpu_memory_buffer_manager_.get(),
3381 NULL,
3383 false,
3384 1));
3386 id = resource_provider->CreateResource(
3387 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
3389 EXPECT_CALL(*context, createImageCHROMIUM(_, kWidth, kHeight, GL_RGBA))
3390 .WillOnce(Return(kImageId))
3391 .RetiresOnSaturation();
3393 ResourceProvider::ScopedWriteLockGpuMemoryBuffer lock(
3394 resource_provider.get(), id);
3395 EXPECT_TRUE(!!lock.GetGpuMemoryBuffer());
3398 EXPECT_CALL(*context, NextTextureId())
3399 .WillOnce(Return(kTextureId))
3400 .RetiresOnSaturation();
3401 // Once in CreateTextureId and once in BindForSampling
3402 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kTextureId)).Times(2)
3403 .RetiresOnSaturation();
3404 EXPECT_CALL(*context, bindTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId))
3405 .Times(1)
3406 .RetiresOnSaturation();
3408 ResourceProvider::ScopedSamplerGL lock_gl(
3409 resource_provider.get(), id, GL_TEXTURE_2D, GL_LINEAR);
3410 EXPECT_EQ(kTextureId, lock_gl.texture_id());
3414 ResourceProvider::ScopedWriteLockGpuMemoryBuffer lock(
3415 resource_provider.get(), id);
3416 EXPECT_TRUE(!!lock.GetGpuMemoryBuffer());
3419 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kTextureId)).Times(1)
3420 .RetiresOnSaturation();
3421 EXPECT_CALL(*context, releaseTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId))
3422 .Times(1)
3423 .RetiresOnSaturation();
3424 EXPECT_CALL(*context, bindTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId))
3425 .Times(1)
3426 .RetiresOnSaturation();
3427 EXPECT_CALL(*context, RetireTextureId(kTextureId))
3428 .Times(1)
3429 .RetiresOnSaturation();
3431 ResourceProvider::ScopedSamplerGL lock_gl(
3432 resource_provider.get(), id, GL_TEXTURE_2D, GL_LINEAR);
3433 EXPECT_EQ(kTextureId, lock_gl.texture_id());
3436 EXPECT_CALL(*context, destroyImageCHROMIUM(kImageId))
3437 .Times(1)
3438 .RetiresOnSaturation();
3441 TEST_P(ResourceProviderTest, CopyResource_GLTexture) {
3442 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
3443 return;
3444 scoped_ptr<AllocationTrackingContext3D> context_owned(
3445 new StrictMock<AllocationTrackingContext3D>);
3446 AllocationTrackingContext3D* context = context_owned.get();
3447 context_owned->set_support_sync_query(true);
3449 FakeOutputSurfaceClient output_surface_client;
3450 scoped_ptr<OutputSurface> output_surface(
3451 FakeOutputSurface::Create3d(context_owned.Pass()));
3452 ASSERT_TRUE(output_surface->BindToClient(&output_surface_client));
3454 const int kWidth = 2;
3455 const int kHeight = 2;
3456 gfx::Size size(kWidth, kHeight);
3457 ResourceFormat format = RGBA_8888;
3458 ResourceProvider::ResourceId source_id = 0;
3459 ResourceProvider::ResourceId dest_id = 0;
3460 const unsigned kSourceTextureId = 123u;
3461 const unsigned kDestTextureId = 321u;
3462 const unsigned kImageId = 234u;
3464 scoped_ptr<ResourceProvider> resource_provider(
3465 ResourceProvider::Create(output_surface.get(),
3466 shared_bitmap_manager_.get(),
3467 gpu_memory_buffer_manager_.get(),
3468 NULL,
3470 false,
3471 1));
3473 source_id = resource_provider->CreateResource(
3474 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
3476 EXPECT_CALL(*context, createImageCHROMIUM(_, kWidth, kHeight, GL_RGBA))
3477 .WillOnce(Return(kImageId))
3478 .RetiresOnSaturation();
3480 ResourceProvider::ScopedWriteLockGpuMemoryBuffer lock(
3481 resource_provider.get(), source_id);
3482 EXPECT_TRUE(!!lock.GetGpuMemoryBuffer());
3484 Mock::VerifyAndClearExpectations(context);
3486 dest_id = resource_provider->CreateResource(
3487 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
3489 EXPECT_CALL(*context, NextTextureId())
3490 .WillOnce(Return(kDestTextureId))
3491 .RetiresOnSaturation();
3492 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kDestTextureId))
3493 .Times(2)
3494 .RetiresOnSaturation();
3495 EXPECT_CALL(*context, texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA,
3496 GL_UNSIGNED_BYTE, nullptr))
3497 .Times(1)
3498 .RetiresOnSaturation();
3499 EXPECT_CALL(*context, NextTextureId())
3500 .WillOnce(Return(kSourceTextureId))
3501 .RetiresOnSaturation();
3502 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kSourceTextureId))
3503 .Times(2)
3504 .RetiresOnSaturation();
3505 EXPECT_CALL(*context, bindTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId))
3506 .Times(1)
3507 .RetiresOnSaturation();
3508 resource_provider->CopyResource(source_id, dest_id);
3509 Mock::VerifyAndClearExpectations(context);
3511 EXPECT_CALL(*context, destroyImageCHROMIUM(kImageId))
3512 .Times(1)
3513 .RetiresOnSaturation();
3514 EXPECT_CALL(*context, RetireTextureId(kSourceTextureId))
3515 .Times(1)
3516 .RetiresOnSaturation();
3517 EXPECT_CALL(*context, RetireTextureId(kDestTextureId))
3518 .Times(1)
3519 .RetiresOnSaturation();
3520 resource_provider->DeleteResource(source_id);
3521 resource_provider->DeleteResource(dest_id);
3524 void InitializeGLAndCheck(ContextSharedData* shared_data,
3525 ResourceProvider* resource_provider,
3526 FakeOutputSurface* output_surface) {
3527 scoped_ptr<ResourceProviderContext> context_owned =
3528 ResourceProviderContext::Create(shared_data);
3529 ResourceProviderContext* context = context_owned.get();
3531 scoped_refptr<TestContextProvider> context_provider =
3532 TestContextProvider::Create(context_owned.Pass());
3533 output_surface->InitializeAndSetContext3d(context_provider, nullptr);
3534 resource_provider->InitializeGL();
3536 CheckCreateResource(ResourceProvider::RESOURCE_TYPE_GL_TEXTURE,
3537 resource_provider, context);
3540 TEST(ResourceProviderTest, BasicInitializeGLSoftware) {
3541 scoped_ptr<ContextSharedData> shared_data = ContextSharedData::Create();
3542 bool delegated_rendering = false;
3543 scoped_ptr<FakeOutputSurface> output_surface(
3544 FakeOutputSurface::CreateDeferredGL(
3545 scoped_ptr<SoftwareOutputDevice>(new SoftwareOutputDevice),
3546 delegated_rendering));
3547 FakeOutputSurfaceClient client(output_surface.get());
3548 EXPECT_TRUE(output_surface->BindToClient(&client));
3549 scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
3550 new TestSharedBitmapManager());
3551 scoped_ptr<ResourceProvider> resource_provider(
3552 ResourceProvider::Create(output_surface.get(),
3553 shared_bitmap_manager.get(),
3554 NULL,
3555 NULL,
3557 false,
3558 1));
3560 CheckCreateResource(ResourceProvider::RESOURCE_TYPE_BITMAP,
3561 resource_provider.get(), NULL);
3563 InitializeGLAndCheck(shared_data.get(),
3564 resource_provider.get(),
3565 output_surface.get());
3567 resource_provider->InitializeSoftware();
3568 output_surface->ReleaseGL();
3569 CheckCreateResource(ResourceProvider::RESOURCE_TYPE_BITMAP,
3570 resource_provider.get(), NULL);
3572 InitializeGLAndCheck(shared_data.get(),
3573 resource_provider.get(),
3574 output_surface.get());
3577 TEST_P(ResourceProviderTest, CompressedTextureETC1Allocate) {
3578 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
3579 return;
3581 scoped_ptr<AllocationTrackingContext3D> context_owned(
3582 new AllocationTrackingContext3D);
3583 AllocationTrackingContext3D* context = context_owned.get();
3584 context_owned->set_support_compressed_texture_etc1(true);
3586 FakeOutputSurfaceClient output_surface_client;
3587 scoped_ptr<OutputSurface> output_surface(
3588 FakeOutputSurface::Create3d(context_owned.Pass()));
3589 CHECK(output_surface->BindToClient(&output_surface_client));
3591 gfx::Size size(4, 4);
3592 scoped_ptr<ResourceProvider> resource_provider(
3593 ResourceProvider::Create(output_surface.get(),
3594 shared_bitmap_manager_.get(),
3595 gpu_memory_buffer_manager_.get(),
3596 NULL,
3598 false,
3599 1));
3600 int texture_id = 123;
3602 ResourceProvider::ResourceId id = resource_provider->CreateResource(
3603 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, ETC1);
3604 EXPECT_NE(0u, id);
3605 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3606 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
3607 resource_provider->AllocateForTesting(id);
3609 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3610 resource_provider->DeleteResource(id);
3613 TEST_P(ResourceProviderTest, CompressedTextureETC1Upload) {
3614 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
3615 return;
3617 scoped_ptr<AllocationTrackingContext3D> context_owned(
3618 new AllocationTrackingContext3D);
3619 AllocationTrackingContext3D* context = context_owned.get();
3620 context_owned->set_support_compressed_texture_etc1(true);
3622 FakeOutputSurfaceClient output_surface_client;
3623 scoped_ptr<OutputSurface> output_surface(
3624 FakeOutputSurface::Create3d(context_owned.Pass()));
3625 CHECK(output_surface->BindToClient(&output_surface_client));
3627 gfx::Size size(4, 4);
3628 scoped_ptr<ResourceProvider> resource_provider(
3629 ResourceProvider::Create(output_surface.get(),
3630 shared_bitmap_manager_.get(),
3631 gpu_memory_buffer_manager_.get(),
3632 NULL,
3634 false,
3635 1));
3636 int texture_id = 123;
3637 uint8_t pixels[8];
3639 ResourceProvider::ResourceId id = resource_provider->CreateResource(
3640 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, ETC1);
3641 EXPECT_NE(0u, id);
3642 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3643 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(3);
3644 EXPECT_CALL(*context,
3645 compressedTexImage2D(
3646 _, 0, _, size.width(), size.height(), _, _, _)).Times(1);
3647 resource_provider->CopyToResource(id, pixels, size);
3649 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3650 resource_provider->DeleteResource(id);
3653 INSTANTIATE_TEST_CASE_P(
3654 ResourceProviderTests,
3655 ResourceProviderTest,
3656 ::testing::Values(ResourceProvider::RESOURCE_TYPE_GL_TEXTURE,
3657 ResourceProvider::RESOURCE_TYPE_BITMAP));
3659 class TextureIdAllocationTrackingContext : public TestWebGraphicsContext3D {
3660 public:
3661 GLuint NextTextureId() override {
3662 base::AutoLock lock(namespace_->lock);
3663 return namespace_->next_texture_id++;
3665 void RetireTextureId(GLuint) override {}
3666 GLuint PeekTextureId() {
3667 base::AutoLock lock(namespace_->lock);
3668 return namespace_->next_texture_id;
3672 TEST(ResourceProviderTest, TextureAllocationChunkSize) {
3673 scoped_ptr<TextureIdAllocationTrackingContext> context_owned(
3674 new TextureIdAllocationTrackingContext);
3675 TextureIdAllocationTrackingContext* context = context_owned.get();
3677 FakeOutputSurfaceClient output_surface_client;
3678 scoped_ptr<OutputSurface> output_surface(
3679 FakeOutputSurface::Create3d(context_owned.Pass()));
3680 CHECK(output_surface->BindToClient(&output_surface_client));
3681 scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
3682 new TestSharedBitmapManager());
3684 gfx::Size size(1, 1);
3685 ResourceFormat format = RGBA_8888;
3688 size_t kTextureAllocationChunkSize = 1;
3689 scoped_ptr<ResourceProvider> resource_provider(
3690 ResourceProvider::Create(output_surface.get(),
3691 shared_bitmap_manager.get(),
3692 NULL,
3693 NULL,
3695 false,
3696 kTextureAllocationChunkSize));
3698 ResourceProvider::ResourceId id = resource_provider->CreateResource(
3699 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE,
3700 format);
3701 resource_provider->AllocateForTesting(id);
3702 Mock::VerifyAndClearExpectations(context);
3704 DCHECK_EQ(2u, context->PeekTextureId());
3705 resource_provider->DeleteResource(id);
3709 size_t kTextureAllocationChunkSize = 8;
3710 scoped_ptr<ResourceProvider> resource_provider(
3711 ResourceProvider::Create(output_surface.get(),
3712 shared_bitmap_manager.get(),
3713 NULL,
3714 NULL,
3716 false,
3717 kTextureAllocationChunkSize));
3719 ResourceProvider::ResourceId id = resource_provider->CreateResource(
3720 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE,
3721 format);
3722 resource_provider->AllocateForTesting(id);
3723 Mock::VerifyAndClearExpectations(context);
3725 DCHECK_EQ(10u, context->PeekTextureId());
3726 resource_provider->DeleteResource(id);
3730 } // namespace
3731 } // namespace cc