Don't show supervised user as "already on this device" while they're being imported.
[chromium-blink-merge.git] / cc / resources / resource_provider_unittest.cc
blobf1152e2773b7a4a1a9614b4481cf0e10ee9f09a1
1 // Copyright 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "cc/resources/resource_provider.h"
7 #include <algorithm>
8 #include <map>
9 #include <set>
11 #include "base/bind.h"
12 #include "base/containers/hash_tables.h"
13 #include "base/logging.h"
14 #include "base/memory/ref_counted.h"
15 #include "cc/base/scoped_ptr_deque.h"
16 #include "cc/output/output_surface.h"
17 #include "cc/resources/returned_resource.h"
18 #include "cc/resources/shared_bitmap_manager.h"
19 #include "cc/resources/single_release_callback.h"
20 #include "cc/test/fake_output_surface.h"
21 #include "cc/test/fake_output_surface_client.h"
22 #include "cc/test/test_gpu_memory_buffer_manager.h"
23 #include "cc/test/test_shared_bitmap_manager.h"
24 #include "cc/test/test_texture.h"
25 #include "cc/test/test_web_graphics_context_3d.h"
26 #include "cc/trees/blocking_task_runner.h"
27 #include "gpu/GLES2/gl2extchromium.h"
28 #include "testing/gmock/include/gmock/gmock.h"
29 #include "testing/gtest/include/gtest/gtest.h"
30 #include "third_party/khronos/GLES2/gl2.h"
31 #include "third_party/khronos/GLES2/gl2ext.h"
32 #include "ui/gfx/geometry/rect.h"
33 #include "ui/gfx/gpu_memory_buffer.h"
35 using testing::Mock;
36 using testing::NiceMock;
37 using testing::Return;
38 using testing::SetArgPointee;
39 using testing::StrictMock;
40 using testing::_;
42 namespace cc {
43 namespace {
45 static void EmptyReleaseCallback(uint32 sync_point,
46 bool lost_resource,
47 BlockingTaskRunner* main_thread_task_runner) {
50 static void ReleaseCallback(
51 uint32* release_sync_point,
52 bool* release_lost_resource,
53 BlockingTaskRunner** release_main_thread_task_runner,
54 uint32 sync_point,
55 bool lost_resource,
56 BlockingTaskRunner* main_thread_task_runner) {
57 *release_sync_point = sync_point;
58 *release_lost_resource = lost_resource;
59 *release_main_thread_task_runner = main_thread_task_runner;
62 static void SharedBitmapReleaseCallback(
63 scoped_ptr<SharedBitmap> bitmap,
64 uint32 sync_point,
65 bool lost_resource,
66 BlockingTaskRunner* main_thread_task_runner) {
69 static void ReleaseSharedBitmapCallback(
70 scoped_ptr<SharedBitmap> shared_bitmap,
71 bool* release_called,
72 uint32* release_sync_point,
73 bool* lost_resource_result,
74 uint32 sync_point,
75 bool lost_resource,
76 BlockingTaskRunner* main_thread_task_runner) {
77 *release_called = true;
78 *release_sync_point = sync_point;
79 *lost_resource_result = lost_resource;
82 static scoped_ptr<SharedBitmap> CreateAndFillSharedBitmap(
83 SharedBitmapManager* manager,
84 const gfx::Size& size,
85 uint32_t value) {
86 scoped_ptr<SharedBitmap> shared_bitmap = manager->AllocateSharedBitmap(size);
87 CHECK(shared_bitmap);
88 uint32_t* pixels = reinterpret_cast<uint32_t*>(shared_bitmap->pixels());
89 CHECK(pixels);
90 std::fill_n(pixels, size.GetArea(), value);
91 return shared_bitmap.Pass();
94 class TextureStateTrackingContext : public TestWebGraphicsContext3D {
95 public:
96 MOCK_METHOD2(bindTexture, void(GLenum target, GLuint texture));
97 MOCK_METHOD3(texParameteri, void(GLenum target, GLenum pname, GLint param));
98 MOCK_METHOD1(waitSyncPoint, void(GLuint sync_point));
99 MOCK_METHOD0(insertSyncPoint, GLuint(void));
100 MOCK_METHOD3(produceTextureDirectCHROMIUM,
101 void(GLuint texture, GLenum target, const GLbyte* mailbox));
102 MOCK_METHOD2(createAndConsumeTextureCHROMIUM,
103 unsigned(GLenum target, const GLbyte* mailbox));
105 // Force all textures to be consecutive numbers starting at "1",
106 // so we easily can test for them.
107 GLuint NextTextureId() override {
108 base::AutoLock lock(namespace_->lock);
109 return namespace_->next_texture_id++;
111 void RetireTextureId(GLuint) override {}
114 // Shared data between multiple ResourceProviderContext. This contains mailbox
115 // contents as well as information about sync points.
116 class ContextSharedData {
117 public:
118 static scoped_ptr<ContextSharedData> Create() {
119 return make_scoped_ptr(new ContextSharedData());
122 uint32 InsertSyncPoint() { return next_sync_point_++; }
124 void GenMailbox(GLbyte* mailbox) {
125 memset(mailbox, 0, GL_MAILBOX_SIZE_CHROMIUM);
126 memcpy(mailbox, &next_mailbox_, sizeof(next_mailbox_));
127 ++next_mailbox_;
130 void ProduceTexture(const GLbyte* mailbox_name,
131 uint32 sync_point,
132 scoped_refptr<TestTexture> texture) {
133 unsigned mailbox = 0;
134 memcpy(&mailbox, mailbox_name, sizeof(mailbox));
135 ASSERT_TRUE(mailbox && mailbox < next_mailbox_);
136 textures_[mailbox] = texture;
137 ASSERT_LT(sync_point_for_mailbox_[mailbox], sync_point);
138 sync_point_for_mailbox_[mailbox] = sync_point;
141 scoped_refptr<TestTexture> ConsumeTexture(const GLbyte* mailbox_name,
142 uint32 sync_point) {
143 unsigned mailbox = 0;
144 memcpy(&mailbox, mailbox_name, sizeof(mailbox));
145 DCHECK(mailbox && mailbox < next_mailbox_);
147 // If the latest sync point the context has waited on is before the sync
148 // point for when the mailbox was set, pretend we never saw that
149 // ProduceTexture.
150 if (sync_point_for_mailbox_[mailbox] > sync_point) {
151 NOTREACHED();
152 return scoped_refptr<TestTexture>();
154 return textures_[mailbox];
157 private:
158 ContextSharedData() : next_sync_point_(1), next_mailbox_(1) {}
160 uint32 next_sync_point_;
161 unsigned next_mailbox_;
162 typedef base::hash_map<unsigned, scoped_refptr<TestTexture>> TextureMap;
163 TextureMap textures_;
164 base::hash_map<unsigned, uint32> sync_point_for_mailbox_;
167 class ResourceProviderContext : public TestWebGraphicsContext3D {
168 public:
169 static scoped_ptr<ResourceProviderContext> Create(
170 ContextSharedData* shared_data) {
171 return make_scoped_ptr(new ResourceProviderContext(shared_data));
174 GLuint insertSyncPoint() override {
175 uint32 sync_point = shared_data_->InsertSyncPoint();
176 // Commit the produceTextureCHROMIUM calls at this point, so that
177 // they're associated with the sync point.
178 for (PendingProduceTextureList::iterator it =
179 pending_produce_textures_.begin();
180 it != pending_produce_textures_.end();
181 ++it) {
182 shared_data_->ProduceTexture(
183 (*it)->mailbox, sync_point, (*it)->texture);
185 pending_produce_textures_.clear();
186 return sync_point;
189 void waitSyncPoint(GLuint sync_point) override {
190 last_waited_sync_point_ = std::max(sync_point, last_waited_sync_point_);
193 unsigned last_waited_sync_point() const { return last_waited_sync_point_; }
195 void texStorage2DEXT(GLenum target,
196 GLint levels,
197 GLuint internalformat,
198 GLint width,
199 GLint height) override {
200 CheckTextureIsBound(target);
201 ASSERT_EQ(static_cast<unsigned>(GL_TEXTURE_2D), target);
202 ASSERT_EQ(1, levels);
203 GLenum format = GL_RGBA;
204 switch (internalformat) {
205 case GL_RGBA8_OES:
206 break;
207 case GL_BGRA8_EXT:
208 format = GL_BGRA_EXT;
209 break;
210 default:
211 NOTREACHED();
213 AllocateTexture(gfx::Size(width, height), format);
216 void texImage2D(GLenum target,
217 GLint level,
218 GLenum internalformat,
219 GLsizei width,
220 GLsizei height,
221 GLint border,
222 GLenum format,
223 GLenum type,
224 const void* pixels) override {
225 CheckTextureIsBound(target);
226 ASSERT_EQ(static_cast<unsigned>(GL_TEXTURE_2D), target);
227 ASSERT_FALSE(level);
228 ASSERT_EQ(internalformat, format);
229 ASSERT_FALSE(border);
230 ASSERT_EQ(static_cast<unsigned>(GL_UNSIGNED_BYTE), type);
231 AllocateTexture(gfx::Size(width, height), format);
232 if (pixels)
233 SetPixels(0, 0, width, height, pixels);
236 void texSubImage2D(GLenum target,
237 GLint level,
238 GLint xoffset,
239 GLint yoffset,
240 GLsizei width,
241 GLsizei height,
242 GLenum format,
243 GLenum type,
244 const void* pixels) override {
245 CheckTextureIsBound(target);
246 ASSERT_EQ(static_cast<unsigned>(GL_TEXTURE_2D), target);
247 ASSERT_FALSE(level);
248 ASSERT_EQ(static_cast<unsigned>(GL_UNSIGNED_BYTE), type);
250 base::AutoLock lock_for_texture_access(namespace_->lock);
251 ASSERT_EQ(GLDataFormat(BoundTexture(target)->format), format);
253 ASSERT_TRUE(pixels);
254 SetPixels(xoffset, yoffset, width, height, pixels);
257 void genMailboxCHROMIUM(GLbyte* mailbox) override {
258 return shared_data_->GenMailbox(mailbox);
261 void produceTextureDirectCHROMIUM(GLuint texture,
262 GLenum target,
263 const GLbyte* mailbox) override {
264 // Delay moving the texture into the mailbox until the next
265 // InsertSyncPoint, so that it is not visible to other contexts that
266 // haven't waited on that sync point.
267 scoped_ptr<PendingProduceTexture> pending(new PendingProduceTexture);
268 memcpy(pending->mailbox, mailbox, sizeof(pending->mailbox));
269 base::AutoLock lock_for_texture_access(namespace_->lock);
270 pending->texture = UnboundTexture(texture);
271 pending_produce_textures_.push_back(pending.Pass());
274 GLuint createAndConsumeTextureCHROMIUM(GLenum target,
275 const GLbyte* mailbox) override {
276 GLuint texture_id = createTexture();
277 base::AutoLock lock_for_texture_access(namespace_->lock);
278 scoped_refptr<TestTexture> texture =
279 shared_data_->ConsumeTexture(mailbox, last_waited_sync_point_);
280 namespace_->textures.Replace(texture_id, texture);
281 return texture_id;
284 void GetPixels(const gfx::Size& size,
285 ResourceFormat format,
286 uint8_t* pixels) {
287 CheckTextureIsBound(GL_TEXTURE_2D);
288 base::AutoLock lock_for_texture_access(namespace_->lock);
289 scoped_refptr<TestTexture> texture = BoundTexture(GL_TEXTURE_2D);
290 ASSERT_EQ(texture->size, size);
291 ASSERT_EQ(texture->format, format);
292 memcpy(pixels, texture->data.get(), TextureSizeBytes(size, format));
295 protected:
296 explicit ResourceProviderContext(ContextSharedData* shared_data)
297 : shared_data_(shared_data),
298 last_waited_sync_point_(0) {}
300 private:
301 void AllocateTexture(const gfx::Size& size, GLenum format) {
302 CheckTextureIsBound(GL_TEXTURE_2D);
303 ResourceFormat texture_format = RGBA_8888;
304 switch (format) {
305 case GL_RGBA:
306 texture_format = RGBA_8888;
307 break;
308 case GL_BGRA_EXT:
309 texture_format = BGRA_8888;
310 break;
312 base::AutoLock lock_for_texture_access(namespace_->lock);
313 BoundTexture(GL_TEXTURE_2D)->Reallocate(size, texture_format);
316 void SetPixels(int xoffset,
317 int yoffset,
318 int width,
319 int height,
320 const void* pixels) {
321 CheckTextureIsBound(GL_TEXTURE_2D);
322 base::AutoLock lock_for_texture_access(namespace_->lock);
323 scoped_refptr<TestTexture> texture = BoundTexture(GL_TEXTURE_2D);
324 ASSERT_TRUE(texture->data.get());
325 ASSERT_TRUE(xoffset >= 0 && xoffset + width <= texture->size.width());
326 ASSERT_TRUE(yoffset >= 0 && yoffset + height <= texture->size.height());
327 ASSERT_TRUE(pixels);
328 size_t in_pitch = TextureSizeBytes(gfx::Size(width, 1), texture->format);
329 size_t out_pitch =
330 TextureSizeBytes(gfx::Size(texture->size.width(), 1), texture->format);
331 uint8_t* dest = texture->data.get() + yoffset * out_pitch +
332 TextureSizeBytes(gfx::Size(xoffset, 1), texture->format);
333 const uint8_t* src = static_cast<const uint8_t*>(pixels);
334 for (int i = 0; i < height; ++i) {
335 memcpy(dest, src, in_pitch);
336 dest += out_pitch;
337 src += in_pitch;
341 struct PendingProduceTexture {
342 GLbyte mailbox[GL_MAILBOX_SIZE_CHROMIUM];
343 scoped_refptr<TestTexture> texture;
345 typedef ScopedPtrDeque<PendingProduceTexture> PendingProduceTextureList;
346 ContextSharedData* shared_data_;
347 GLuint last_waited_sync_point_;
348 PendingProduceTextureList pending_produce_textures_;
351 void GetResourcePixels(ResourceProvider* resource_provider,
352 ResourceProviderContext* context,
353 ResourceId id,
354 const gfx::Size& size,
355 ResourceFormat format,
356 uint8_t* pixels) {
357 resource_provider->WaitSyncPointIfNeeded(id);
358 switch (resource_provider->default_resource_type()) {
359 case ResourceProvider::RESOURCE_TYPE_GL_TEXTURE: {
360 ResourceProvider::ScopedReadLockGL lock_gl(resource_provider, id);
361 ASSERT_NE(0U, lock_gl.texture_id());
362 context->bindTexture(GL_TEXTURE_2D, lock_gl.texture_id());
363 context->GetPixels(size, format, pixels);
364 break;
366 case ResourceProvider::RESOURCE_TYPE_BITMAP: {
367 ResourceProvider::ScopedReadLockSoftware lock_software(resource_provider,
368 id);
369 memcpy(pixels,
370 lock_software.sk_bitmap()->getPixels(),
371 lock_software.sk_bitmap()->getSize());
372 break;
377 class ResourceProviderTest
378 : public testing::TestWithParam<ResourceProvider::ResourceType> {
379 public:
380 explicit ResourceProviderTest(bool child_needs_sync_point)
381 : shared_data_(ContextSharedData::Create()),
382 context3d_(NULL),
383 child_context_(NULL),
384 main_thread_task_runner_(BlockingTaskRunner::Create(NULL)) {
385 switch (GetParam()) {
386 case ResourceProvider::RESOURCE_TYPE_GL_TEXTURE: {
387 scoped_ptr<ResourceProviderContext> context3d(
388 ResourceProviderContext::Create(shared_data_.get()));
389 context3d_ = context3d.get();
391 scoped_refptr<TestContextProvider> context_provider =
392 TestContextProvider::Create(context3d.Pass());
394 output_surface_ = FakeOutputSurface::Create3d(context_provider);
396 scoped_ptr<ResourceProviderContext> child_context_owned =
397 ResourceProviderContext::Create(shared_data_.get());
398 child_context_ = child_context_owned.get();
399 if (child_needs_sync_point) {
400 child_output_surface_ =
401 FakeOutputSurface::Create3d(child_context_owned.Pass());
402 } else {
403 child_output_surface_ = FakeOutputSurface::CreateNoRequireSyncPoint(
404 child_context_owned.Pass());
406 break;
408 case ResourceProvider::RESOURCE_TYPE_BITMAP:
409 output_surface_ = FakeOutputSurface::CreateSoftware(
410 make_scoped_ptr(new SoftwareOutputDevice));
411 child_output_surface_ = FakeOutputSurface::CreateSoftware(
412 make_scoped_ptr(new SoftwareOutputDevice));
413 break;
415 CHECK(output_surface_->BindToClient(&output_surface_client_));
416 CHECK(child_output_surface_->BindToClient(&child_output_surface_client_));
418 shared_bitmap_manager_.reset(new TestSharedBitmapManager);
419 gpu_memory_buffer_manager_.reset(new TestGpuMemoryBufferManager);
421 resource_provider_ =
422 ResourceProvider::Create(output_surface_.get(),
423 shared_bitmap_manager_.get(),
424 gpu_memory_buffer_manager_.get(),
425 main_thread_task_runner_.get(),
427 false,
429 child_resource_provider_ =
430 ResourceProvider::Create(child_output_surface_.get(),
431 shared_bitmap_manager_.get(),
432 gpu_memory_buffer_manager_.get(),
433 main_thread_task_runner_.get(),
435 false,
439 ResourceProviderTest() : ResourceProviderTest(true) {}
441 static void CollectResources(ReturnedResourceArray* array,
442 const ReturnedResourceArray& returned,
443 BlockingTaskRunner* main_thread_task_runner) {
444 array->insert(array->end(), returned.begin(), returned.end());
447 static ReturnCallback GetReturnCallback(ReturnedResourceArray* array) {
448 return base::Bind(&ResourceProviderTest::CollectResources, array);
451 static void SetResourceFilter(ResourceProvider* resource_provider,
452 ResourceId id,
453 GLenum filter) {
454 ResourceProvider::ScopedSamplerGL sampler(
455 resource_provider, id, GL_TEXTURE_2D, filter);
458 ResourceProviderContext* context() { return context3d_; }
460 ResourceId CreateChildMailbox(uint32* release_sync_point,
461 bool* lost_resource,
462 bool* release_called,
463 uint32* sync_point) {
464 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) {
465 unsigned texture = child_context_->createTexture();
466 gpu::Mailbox gpu_mailbox;
467 child_context_->genMailboxCHROMIUM(gpu_mailbox.name);
468 child_context_->produceTextureDirectCHROMIUM(texture, GL_TEXTURE_2D,
469 gpu_mailbox.name);
470 *sync_point = child_context_->insertSyncPoint();
471 EXPECT_LT(0u, *sync_point);
473 scoped_ptr<SharedBitmap> shared_bitmap;
474 scoped_ptr<SingleReleaseCallbackImpl> callback =
475 SingleReleaseCallbackImpl::Create(base::Bind(
476 ReleaseSharedBitmapCallback, base::Passed(&shared_bitmap),
477 release_called, release_sync_point, lost_resource));
478 return child_resource_provider_->CreateResourceFromTextureMailbox(
479 TextureMailbox(gpu_mailbox, GL_TEXTURE_2D, *sync_point),
480 callback.Pass());
481 } else {
482 gfx::Size size(64, 64);
483 scoped_ptr<SharedBitmap> shared_bitmap(
484 CreateAndFillSharedBitmap(shared_bitmap_manager_.get(), size, 0));
486 SharedBitmap* shared_bitmap_ptr = shared_bitmap.get();
487 scoped_ptr<SingleReleaseCallbackImpl> callback =
488 SingleReleaseCallbackImpl::Create(base::Bind(
489 ReleaseSharedBitmapCallback, base::Passed(&shared_bitmap),
490 release_called, release_sync_point, lost_resource));
491 return child_resource_provider_->CreateResourceFromTextureMailbox(
492 TextureMailbox(shared_bitmap_ptr, size), callback.Pass());
496 protected:
497 scoped_ptr<ContextSharedData> shared_data_;
498 ResourceProviderContext* context3d_;
499 ResourceProviderContext* child_context_;
500 FakeOutputSurfaceClient output_surface_client_;
501 FakeOutputSurfaceClient child_output_surface_client_;
502 scoped_ptr<OutputSurface> output_surface_;
503 scoped_ptr<OutputSurface> child_output_surface_;
504 scoped_ptr<BlockingTaskRunner> main_thread_task_runner_;
505 scoped_ptr<ResourceProvider> resource_provider_;
506 scoped_ptr<ResourceProvider> child_resource_provider_;
507 scoped_ptr<TestSharedBitmapManager> shared_bitmap_manager_;
508 scoped_ptr<TestGpuMemoryBufferManager> gpu_memory_buffer_manager_;
511 void CheckCreateResource(ResourceProvider::ResourceType expected_default_type,
512 ResourceProvider* resource_provider,
513 ResourceProviderContext* context) {
514 DCHECK_EQ(expected_default_type, resource_provider->default_resource_type());
516 gfx::Size size(1, 1);
517 ResourceFormat format = RGBA_8888;
518 size_t pixel_size = TextureSizeBytes(size, format);
519 ASSERT_EQ(4U, pixel_size);
521 ResourceId id = resource_provider->CreateResource(
522 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
523 EXPECT_EQ(1, static_cast<int>(resource_provider->num_resources()));
524 if (expected_default_type == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
525 EXPECT_EQ(0u, context->NumTextures());
527 uint8_t data[4] = { 1, 2, 3, 4 };
528 resource_provider->CopyToResource(id, data, size);
529 if (expected_default_type == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
530 EXPECT_EQ(1u, context->NumTextures());
532 uint8_t result[4] = { 0 };
533 GetResourcePixels(resource_provider, context, id, size, format, result);
534 EXPECT_EQ(0, memcmp(data, result, pixel_size));
536 resource_provider->DeleteResource(id);
537 EXPECT_EQ(0, static_cast<int>(resource_provider->num_resources()));
538 if (expected_default_type == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
539 EXPECT_EQ(0u, context->NumTextures());
542 TEST_P(ResourceProviderTest, Basic) {
543 CheckCreateResource(GetParam(), resource_provider_.get(), context());
546 TEST_P(ResourceProviderTest, Upload) {
547 gfx::Size size(2, 2);
548 ResourceFormat format = RGBA_8888;
549 size_t pixel_size = TextureSizeBytes(size, format);
550 ASSERT_EQ(16U, pixel_size);
552 ResourceId id = resource_provider_->CreateResource(
553 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
555 uint8_t image[16] = { 0 };
556 gfx::Rect image_rect(size);
557 resource_provider_->SetPixels(
558 id, image, image_rect, image_rect, gfx::Vector2d());
560 for (uint8_t i = 0; i < pixel_size; ++i)
561 image[i] = i;
563 uint8_t result[16] = { 0 };
565 gfx::Rect source_rect(0, 0, 1, 1);
566 gfx::Vector2d dest_offset(0, 0);
567 resource_provider_->SetPixels(
568 id, image, image_rect, source_rect, dest_offset);
570 uint8_t expected[16] = { 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
571 GetResourcePixels(
572 resource_provider_.get(), context(), id, size, format, result);
573 EXPECT_EQ(0, memcmp(expected, result, pixel_size));
576 gfx::Rect source_rect(0, 0, 1, 1);
577 gfx::Vector2d dest_offset(1, 1);
578 resource_provider_->SetPixels(
579 id, image, image_rect, source_rect, dest_offset);
581 uint8_t expected[16] = { 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3 };
582 GetResourcePixels(
583 resource_provider_.get(), context(), id, size, format, result);
584 EXPECT_EQ(0, memcmp(expected, result, pixel_size));
587 gfx::Rect source_rect(1, 0, 1, 1);
588 gfx::Vector2d dest_offset(0, 1);
589 resource_provider_->SetPixels(
590 id, image, image_rect, source_rect, dest_offset);
592 uint8_t expected[16] = { 0, 1, 2, 3, 0, 0, 0, 0, 4, 5, 6, 7, 0, 1, 2, 3 };
593 GetResourcePixels(
594 resource_provider_.get(), context(), id, size, format, result);
595 EXPECT_EQ(0, memcmp(expected, result, pixel_size));
598 gfx::Rect offset_image_rect(gfx::Point(100, 100), size);
599 gfx::Rect source_rect(100, 100, 1, 1);
600 gfx::Vector2d dest_offset(1, 0);
601 resource_provider_->SetPixels(
602 id, image, offset_image_rect, source_rect, dest_offset);
604 uint8_t expected[16] = { 0, 1, 2, 3, 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3 };
605 GetResourcePixels(
606 resource_provider_.get(), context(), id, size, format, result);
607 EXPECT_EQ(0, memcmp(expected, result, pixel_size));
610 resource_provider_->DeleteResource(id);
613 TEST_P(ResourceProviderTest, SimpleUpload) {
614 gfx::Size size(2, 2);
615 ResourceFormat format = RGBA_8888;
616 size_t pixel_size = TextureSizeBytes(size, format);
617 ASSERT_EQ(16U, pixel_size);
619 ResourceId id = resource_provider_->CreateResource(
620 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
622 uint8_t image[16] = {0};
623 resource_provider_->CopyToResource(id, image, size);
625 uint8_t result[16] = {0};
626 uint8_t expected[16] = {0};
627 GetResourcePixels(resource_provider_.get(), context(), id, size, format,
628 result);
629 EXPECT_EQ(0, memcmp(expected, result, pixel_size));
632 for (uint8_t i = 0; i < pixel_size; ++i)
633 image[i] = i;
634 resource_provider_->CopyToResource(id, image, size);
636 uint8_t result[16] = {0};
637 uint8_t expected[16] = {
638 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
639 GetResourcePixels(resource_provider_.get(), context(), id, size, format,
640 result);
641 EXPECT_EQ(0, memcmp(expected, result, pixel_size));
645 TEST_P(ResourceProviderTest, TransferGLResources) {
646 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
647 return;
648 gfx::Size size(1, 1);
649 ResourceFormat format = RGBA_8888;
650 size_t pixel_size = TextureSizeBytes(size, format);
651 ASSERT_EQ(4U, pixel_size);
653 ResourceId id1 = child_resource_provider_->CreateResource(
654 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
655 uint8_t data1[4] = { 1, 2, 3, 4 };
656 child_resource_provider_->CopyToResource(id1, data1, size);
658 ResourceId id2 = child_resource_provider_->CreateResource(
659 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
660 uint8_t data2[4] = { 5, 5, 5, 5 };
661 child_resource_provider_->CopyToResource(id2, data2, size);
663 ResourceId id3 = child_resource_provider_->CreateResource(
664 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
666 ResourceProvider::ScopedWriteLockGpuMemoryBuffer lock(
667 child_resource_provider_.get(), id3);
668 EXPECT_TRUE(lock.GetGpuMemoryBuffer());
671 GLuint external_texture_id = child_context_->createExternalTexture();
673 gpu::Mailbox external_mailbox;
674 child_context_->genMailboxCHROMIUM(external_mailbox.name);
675 child_context_->produceTextureDirectCHROMIUM(
676 external_texture_id, GL_TEXTURE_EXTERNAL_OES, external_mailbox.name);
677 const GLuint external_sync_point = child_context_->insertSyncPoint();
678 ResourceId id4 = child_resource_provider_->CreateResourceFromTextureMailbox(
679 TextureMailbox(external_mailbox, GL_TEXTURE_EXTERNAL_OES,
680 external_sync_point),
681 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback)));
683 ReturnedResourceArray returned_to_child;
684 int child_id =
685 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
687 // Transfer some resources to the parent.
688 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
689 resource_ids_to_transfer.push_back(id1);
690 resource_ids_to_transfer.push_back(id2);
691 resource_ids_to_transfer.push_back(id3);
692 resource_ids_to_transfer.push_back(id4);
693 TransferableResourceArray list;
694 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
695 &list);
696 ASSERT_EQ(4u, list.size());
697 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
698 EXPECT_NE(0u, list[1].mailbox_holder.sync_point);
699 EXPECT_EQ(list[0].mailbox_holder.sync_point,
700 list[1].mailbox_holder.sync_point);
701 EXPECT_NE(0u, list[2].mailbox_holder.sync_point);
702 EXPECT_EQ(list[0].mailbox_holder.sync_point,
703 list[2].mailbox_holder.sync_point);
704 EXPECT_EQ(external_sync_point, list[3].mailbox_holder.sync_point);
705 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
706 list[0].mailbox_holder.texture_target);
707 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
708 list[1].mailbox_holder.texture_target);
709 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
710 list[2].mailbox_holder.texture_target);
711 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_EXTERNAL_OES),
712 list[3].mailbox_holder.texture_target);
713 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
714 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
715 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
716 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id4));
717 resource_provider_->ReceiveFromChild(child_id, list);
718 EXPECT_NE(list[0].mailbox_holder.sync_point,
719 context3d_->last_waited_sync_point());
721 resource_provider_->WaitSyncPointIfNeeded(list[0].id);
722 ResourceProvider::ScopedReadLockGL lock(resource_provider_.get(),
723 list[0].id);
725 EXPECT_EQ(list[0].mailbox_holder.sync_point,
726 context3d_->last_waited_sync_point());
727 ResourceProvider::ResourceIdSet resource_ids_to_receive;
728 resource_ids_to_receive.insert(id1);
729 resource_ids_to_receive.insert(id2);
730 resource_ids_to_receive.insert(id3);
731 resource_ids_to_receive.insert(id4);
732 resource_provider_->DeclareUsedResourcesFromChild(child_id,
733 resource_ids_to_receive);
736 EXPECT_EQ(4u, resource_provider_->num_resources());
737 ResourceProvider::ResourceIdMap resource_map =
738 resource_provider_->GetChildToParentMap(child_id);
739 ResourceId mapped_id1 = resource_map[id1];
740 ResourceId mapped_id2 = resource_map[id2];
741 ResourceId mapped_id3 = resource_map[id3];
742 ResourceId mapped_id4 = resource_map[id4];
743 EXPECT_NE(0u, mapped_id1);
744 EXPECT_NE(0u, mapped_id2);
745 EXPECT_NE(0u, mapped_id3);
746 EXPECT_NE(0u, mapped_id4);
747 EXPECT_FALSE(resource_provider_->InUseByConsumer(id1));
748 EXPECT_FALSE(resource_provider_->InUseByConsumer(id2));
749 EXPECT_FALSE(resource_provider_->InUseByConsumer(id3));
750 EXPECT_FALSE(resource_provider_->InUseByConsumer(id4));
752 uint8_t result[4] = { 0 };
753 GetResourcePixels(
754 resource_provider_.get(), context(), mapped_id1, size, format, result);
755 EXPECT_EQ(0, memcmp(data1, result, pixel_size));
757 GetResourcePixels(
758 resource_provider_.get(), context(), mapped_id2, size, format, result);
759 EXPECT_EQ(0, memcmp(data2, result, pixel_size));
762 // Check that transfering again the same resource from the child to the
763 // parent works.
764 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
765 resource_ids_to_transfer.push_back(id1);
766 resource_ids_to_transfer.push_back(id2);
767 resource_ids_to_transfer.push_back(id3);
768 TransferableResourceArray list;
769 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
770 &list);
771 EXPECT_EQ(3u, list.size());
772 EXPECT_EQ(id1, list[0].id);
773 EXPECT_EQ(id2, list[1].id);
774 EXPECT_EQ(id3, list[2].id);
775 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
776 list[0].mailbox_holder.texture_target);
777 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
778 list[1].mailbox_holder.texture_target);
779 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
780 list[2].mailbox_holder.texture_target);
781 ReturnedResourceArray returned;
782 TransferableResource::ReturnResources(list, &returned);
783 child_resource_provider_->ReceiveReturnsFromParent(returned);
784 // ids were exported twice, we returned them only once, they should still
785 // be in-use.
786 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
787 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
788 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
791 EXPECT_EQ(0u, returned_to_child.size());
793 // Transfer resources back from the parent to the child. Set no resources as
794 // being in use.
795 ResourceProvider::ResourceIdSet no_resources;
796 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
798 ASSERT_EQ(4u, returned_to_child.size());
799 EXPECT_NE(0u, returned_to_child[0].sync_point);
800 EXPECT_NE(0u, returned_to_child[1].sync_point);
801 EXPECT_NE(0u, returned_to_child[2].sync_point);
802 EXPECT_NE(0u, returned_to_child[3].sync_point);
803 EXPECT_FALSE(returned_to_child[0].lost);
804 EXPECT_FALSE(returned_to_child[1].lost);
805 EXPECT_FALSE(returned_to_child[2].lost);
806 EXPECT_FALSE(returned_to_child[3].lost);
807 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
808 returned_to_child.clear();
810 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id1));
811 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id2));
812 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id3));
813 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id4));
816 child_resource_provider_->WaitSyncPointIfNeeded(id1);
817 ResourceProvider::ScopedReadLockGL lock(child_resource_provider_.get(),
818 id1);
819 ASSERT_NE(0U, lock.texture_id());
820 child_context_->bindTexture(GL_TEXTURE_2D, lock.texture_id());
821 child_context_->GetPixels(size, format, result);
822 EXPECT_EQ(0, memcmp(data1, result, pixel_size));
825 child_resource_provider_->WaitSyncPointIfNeeded(id2);
826 ResourceProvider::ScopedReadLockGL lock(child_resource_provider_.get(),
827 id2);
828 ASSERT_NE(0U, lock.texture_id());
829 child_context_->bindTexture(GL_TEXTURE_2D, lock.texture_id());
830 child_context_->GetPixels(size, format, result);
831 EXPECT_EQ(0, memcmp(data2, result, pixel_size));
834 child_resource_provider_->WaitSyncPointIfNeeded(id3);
835 ResourceProvider::ScopedReadLockGL lock(child_resource_provider_.get(),
836 id3);
837 ASSERT_NE(0U, lock.texture_id());
838 child_context_->bindTexture(GL_TEXTURE_2D, lock.texture_id());
841 // Transfer resources to the parent again.
842 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
843 resource_ids_to_transfer.push_back(id1);
844 resource_ids_to_transfer.push_back(id2);
845 resource_ids_to_transfer.push_back(id3);
846 resource_ids_to_transfer.push_back(id4);
847 TransferableResourceArray list;
848 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
849 &list);
850 ASSERT_EQ(4u, list.size());
851 EXPECT_EQ(id1, list[0].id);
852 EXPECT_EQ(id2, list[1].id);
853 EXPECT_EQ(id3, list[2].id);
854 EXPECT_EQ(id4, list[3].id);
855 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
856 EXPECT_NE(0u, list[1].mailbox_holder.sync_point);
857 EXPECT_NE(0u, list[2].mailbox_holder.sync_point);
858 EXPECT_NE(0u, list[3].mailbox_holder.sync_point);
859 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
860 list[0].mailbox_holder.texture_target);
861 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
862 list[1].mailbox_holder.texture_target);
863 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
864 list[2].mailbox_holder.texture_target);
865 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_EXTERNAL_OES),
866 list[3].mailbox_holder.texture_target);
867 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
868 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
869 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
870 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id4));
871 resource_provider_->ReceiveFromChild(child_id, list);
872 ResourceProvider::ResourceIdSet resource_ids_to_receive;
873 resource_ids_to_receive.insert(id1);
874 resource_ids_to_receive.insert(id2);
875 resource_ids_to_receive.insert(id3);
876 resource_ids_to_receive.insert(id4);
877 resource_provider_->DeclareUsedResourcesFromChild(child_id,
878 resource_ids_to_receive);
881 EXPECT_EQ(0u, returned_to_child.size());
883 EXPECT_EQ(4u, resource_provider_->num_resources());
884 resource_provider_->DestroyChild(child_id);
885 EXPECT_EQ(0u, resource_provider_->num_resources());
887 ASSERT_EQ(4u, returned_to_child.size());
888 EXPECT_NE(0u, returned_to_child[0].sync_point);
889 EXPECT_NE(0u, returned_to_child[1].sync_point);
890 EXPECT_NE(0u, returned_to_child[2].sync_point);
891 EXPECT_NE(0u, returned_to_child[3].sync_point);
892 EXPECT_FALSE(returned_to_child[0].lost);
893 EXPECT_FALSE(returned_to_child[1].lost);
894 EXPECT_FALSE(returned_to_child[2].lost);
895 EXPECT_FALSE(returned_to_child[3].lost);
898 class ResourceProviderTestNoSyncPoint : public ResourceProviderTest {
899 public:
900 ResourceProviderTestNoSyncPoint() : ResourceProviderTest(false) {
901 EXPECT_EQ(ResourceProvider::RESOURCE_TYPE_GL_TEXTURE, GetParam());
905 TEST_P(ResourceProviderTestNoSyncPoint, TransferGLResources) {
906 gfx::Size size(1, 1);
907 ResourceFormat format = RGBA_8888;
908 size_t pixel_size = TextureSizeBytes(size, format);
909 ASSERT_EQ(4U, pixel_size);
911 ResourceId id1 = child_resource_provider_->CreateResource(
912 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
913 uint8_t data1[4] = {1, 2, 3, 4};
914 child_resource_provider_->CopyToResource(id1, data1, size);
916 ResourceId id2 = child_resource_provider_->CreateResource(
917 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
919 // Ensure locking the memory buffer doesn't create an unnecessary sync
920 // point.
921 ResourceProvider::ScopedWriteLockGpuMemoryBuffer lock(
922 child_resource_provider_.get(), id2);
923 EXPECT_TRUE(lock.GetGpuMemoryBuffer());
926 GLuint external_texture_id = child_context_->createExternalTexture();
928 // A sync point is specified directly and should be used.
929 gpu::Mailbox external_mailbox;
930 child_context_->genMailboxCHROMIUM(external_mailbox.name);
931 child_context_->produceTextureDirectCHROMIUM(
932 external_texture_id, GL_TEXTURE_EXTERNAL_OES, external_mailbox.name);
933 const GLuint external_sync_point = child_context_->insertSyncPoint();
934 ResourceId id3 = child_resource_provider_->CreateResourceFromTextureMailbox(
935 TextureMailbox(external_mailbox, GL_TEXTURE_EXTERNAL_OES,
936 external_sync_point),
937 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback)));
939 ReturnedResourceArray returned_to_child;
940 int child_id =
941 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
942 resource_provider_->SetChildNeedsSyncPoints(child_id, false);
944 // Transfer some resources to the parent.
945 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
946 resource_ids_to_transfer.push_back(id1);
947 resource_ids_to_transfer.push_back(id2);
948 resource_ids_to_transfer.push_back(id3);
949 TransferableResourceArray list;
950 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
951 &list);
952 ASSERT_EQ(3u, list.size());
953 // Standard resources shouldn't require creating and sending a sync point.
954 EXPECT_EQ(0u, list[0].mailbox_holder.sync_point);
955 EXPECT_EQ(0u, list[1].mailbox_holder.sync_point);
956 // A given sync point should be passed through.
957 EXPECT_EQ(external_sync_point, list[2].mailbox_holder.sync_point);
958 resource_provider_->ReceiveFromChild(child_id, list);
960 ResourceProvider::ResourceIdSet resource_ids_to_receive;
961 resource_ids_to_receive.insert(id1);
962 resource_ids_to_receive.insert(id2);
963 resource_ids_to_receive.insert(id3);
964 resource_provider_->DeclareUsedResourcesFromChild(child_id,
965 resource_ids_to_receive);
969 EXPECT_EQ(0u, returned_to_child.size());
971 // Transfer resources back from the parent to the child. Set no resources as
972 // being in use.
973 ResourceProvider::ResourceIdSet no_resources;
974 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
976 ASSERT_EQ(3u, returned_to_child.size());
977 std::map<ResourceId, unsigned int> returned_sync_points;
978 for (const auto& returned : returned_to_child)
979 returned_sync_points[returned.id] = returned.sync_point;
981 EXPECT_TRUE(returned_sync_points.find(id1) != returned_sync_points.end());
982 // No new sync point should be created transferring back.
983 EXPECT_TRUE(returned_sync_points.find(id1) != returned_sync_points.end());
984 EXPECT_EQ(0u, returned_sync_points[id1]);
985 EXPECT_TRUE(returned_sync_points.find(id2) != returned_sync_points.end());
986 EXPECT_EQ(0u, returned_sync_points[id2]);
987 // Original sync point given should be returned.
988 EXPECT_TRUE(returned_sync_points.find(id3) != returned_sync_points.end());
989 EXPECT_EQ(external_sync_point, returned_sync_points[id3]);
990 EXPECT_FALSE(returned_to_child[0].lost);
991 EXPECT_FALSE(returned_to_child[1].lost);
992 EXPECT_FALSE(returned_to_child[2].lost);
993 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
994 returned_to_child.clear();
997 resource_provider_->DestroyChild(child_id);
1000 INSTANTIATE_TEST_CASE_P(
1001 ResourceProviderTests,
1002 ResourceProviderTestNoSyncPoint,
1003 ::testing::Values(ResourceProvider::RESOURCE_TYPE_GL_TEXTURE));
1005 TEST_P(ResourceProviderTest, ReadLockCountStopsReturnToChildOrDelete) {
1006 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
1007 return;
1008 gfx::Size size(1, 1);
1009 ResourceFormat format = RGBA_8888;
1011 ResourceId id1 = child_resource_provider_->CreateResource(
1012 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
1013 uint8_t data1[4] = {1, 2, 3, 4};
1014 child_resource_provider_->CopyToResource(id1, data1, size);
1016 ReturnedResourceArray returned_to_child;
1017 int child_id =
1018 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1020 // Transfer some resources to the parent.
1021 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1022 resource_ids_to_transfer.push_back(id1);
1023 TransferableResourceArray list;
1024 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1025 &list);
1026 ASSERT_EQ(1u, list.size());
1027 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1029 resource_provider_->ReceiveFromChild(child_id, list);
1031 resource_provider_->WaitSyncPointIfNeeded(list[0].id);
1032 ResourceProvider::ScopedReadLockGL lock(resource_provider_.get(),
1033 list[0].id);
1035 resource_provider_->DeclareUsedResourcesFromChild(
1036 child_id, ResourceProvider::ResourceIdSet());
1037 EXPECT_EQ(0u, returned_to_child.size());
1040 EXPECT_EQ(1u, returned_to_child.size());
1041 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
1044 child_resource_provider_->WaitSyncPointIfNeeded(id1);
1045 ResourceProvider::ScopedReadLockGL lock(child_resource_provider_.get(),
1046 id1);
1047 child_resource_provider_->DeleteResource(id1);
1048 EXPECT_EQ(1u, child_resource_provider_->num_resources());
1049 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1052 EXPECT_EQ(0u, child_resource_provider_->num_resources());
1053 resource_provider_->DestroyChild(child_id);
1056 TEST_P(ResourceProviderTest, AllowOverlayTransfersToParent) {
1057 // Overlays only supported on the GL path.
1058 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
1059 return;
1061 uint32 sync_point = 0;
1062 TextureMailbox mailbox(gpu::Mailbox::Generate(), GL_TEXTURE_2D, sync_point);
1063 mailbox.set_allow_overlay(true);
1064 scoped_ptr<SingleReleaseCallbackImpl> release_callback =
1065 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback));
1066 ResourceId id1 = child_resource_provider_->CreateResourceFromTextureMailbox(
1067 mailbox, release_callback.Pass());
1069 TextureMailbox mailbox2(gpu::Mailbox::Generate(), GL_TEXTURE_2D, sync_point);
1070 mailbox2.set_allow_overlay(false);
1071 scoped_ptr<SingleReleaseCallbackImpl> release_callback2 =
1072 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback));
1073 ResourceId id2 = child_resource_provider_->CreateResourceFromTextureMailbox(
1074 mailbox2, release_callback2.Pass());
1076 ReturnedResourceArray returned_to_child;
1077 int child_id =
1078 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1080 // Transfer some resources to the parent.
1081 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1082 resource_ids_to_transfer.push_back(id1);
1083 resource_ids_to_transfer.push_back(id2);
1084 TransferableResourceArray list;
1085 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1086 &list);
1087 ASSERT_EQ(2u, list.size());
1088 resource_provider_->ReceiveFromChild(child_id, list);
1089 EXPECT_TRUE(resource_provider_->AllowOverlay(list[0].id));
1090 EXPECT_FALSE(resource_provider_->AllowOverlay(list[1].id));
1092 resource_provider_->DeclareUsedResourcesFromChild(
1093 child_id, ResourceProvider::ResourceIdSet());
1095 EXPECT_EQ(2u, returned_to_child.size());
1096 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
1098 child_resource_provider_->DeleteResource(id1);
1099 child_resource_provider_->DeleteResource(id2);
1100 EXPECT_EQ(0u, child_resource_provider_->num_resources());
1102 resource_provider_->DestroyChild(child_id);
1105 TEST_P(ResourceProviderTest, TransferSoftwareResources) {
1106 if (GetParam() != ResourceProvider::RESOURCE_TYPE_BITMAP)
1107 return;
1109 gfx::Size size(1, 1);
1110 ResourceFormat format = RGBA_8888;
1111 size_t pixel_size = TextureSizeBytes(size, format);
1112 ASSERT_EQ(4U, pixel_size);
1114 ResourceId id1 = child_resource_provider_->CreateResource(
1115 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
1116 uint8_t data1[4] = { 1, 2, 3, 4 };
1117 child_resource_provider_->CopyToResource(id1, data1, size);
1119 ResourceId id2 = child_resource_provider_->CreateResource(
1120 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
1121 uint8_t data2[4] = { 5, 5, 5, 5 };
1122 child_resource_provider_->CopyToResource(id2, data2, size);
1124 scoped_ptr<SharedBitmap> shared_bitmap(CreateAndFillSharedBitmap(
1125 shared_bitmap_manager_.get(), gfx::Size(1, 1), 0));
1126 SharedBitmap* shared_bitmap_ptr = shared_bitmap.get();
1127 ResourceId id3 = child_resource_provider_->CreateResourceFromTextureMailbox(
1128 TextureMailbox(shared_bitmap_ptr, gfx::Size(1, 1)),
1129 SingleReleaseCallbackImpl::Create(base::Bind(
1130 &SharedBitmapReleaseCallback, base::Passed(&shared_bitmap))));
1132 ReturnedResourceArray returned_to_child;
1133 int child_id =
1134 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1136 // Transfer some resources to the parent.
1137 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1138 resource_ids_to_transfer.push_back(id1);
1139 resource_ids_to_transfer.push_back(id2);
1140 resource_ids_to_transfer.push_back(id3);
1141 TransferableResourceArray list;
1142 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1143 &list);
1144 ASSERT_EQ(3u, list.size());
1145 EXPECT_EQ(0u, list[0].mailbox_holder.sync_point);
1146 EXPECT_EQ(0u, list[1].mailbox_holder.sync_point);
1147 EXPECT_EQ(0u, list[2].mailbox_holder.sync_point);
1148 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1149 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
1150 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
1151 resource_provider_->ReceiveFromChild(child_id, list);
1152 ResourceProvider::ResourceIdSet resource_ids_to_receive;
1153 resource_ids_to_receive.insert(id1);
1154 resource_ids_to_receive.insert(id2);
1155 resource_ids_to_receive.insert(id3);
1156 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1157 resource_ids_to_receive);
1160 EXPECT_EQ(3u, resource_provider_->num_resources());
1161 ResourceProvider::ResourceIdMap resource_map =
1162 resource_provider_->GetChildToParentMap(child_id);
1163 ResourceId mapped_id1 = resource_map[id1];
1164 ResourceId mapped_id2 = resource_map[id2];
1165 ResourceId mapped_id3 = resource_map[id3];
1166 EXPECT_NE(0u, mapped_id1);
1167 EXPECT_NE(0u, mapped_id2);
1168 EXPECT_NE(0u, mapped_id3);
1169 EXPECT_FALSE(resource_provider_->InUseByConsumer(id1));
1170 EXPECT_FALSE(resource_provider_->InUseByConsumer(id2));
1171 EXPECT_FALSE(resource_provider_->InUseByConsumer(id3));
1173 uint8_t result[4] = { 0 };
1174 GetResourcePixels(
1175 resource_provider_.get(), context(), mapped_id1, size, format, result);
1176 EXPECT_EQ(0, memcmp(data1, result, pixel_size));
1178 GetResourcePixels(
1179 resource_provider_.get(), context(), mapped_id2, size, format, result);
1180 EXPECT_EQ(0, memcmp(data2, result, pixel_size));
1183 // Check that transfering again the same resource from the child to the
1184 // parent works.
1185 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1186 resource_ids_to_transfer.push_back(id1);
1187 resource_ids_to_transfer.push_back(id2);
1188 TransferableResourceArray list;
1189 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1190 &list);
1191 EXPECT_EQ(2u, list.size());
1192 EXPECT_EQ(id1, list[0].id);
1193 EXPECT_EQ(id2, list[1].id);
1194 ReturnedResourceArray returned;
1195 TransferableResource::ReturnResources(list, &returned);
1196 child_resource_provider_->ReceiveReturnsFromParent(returned);
1197 // ids were exported twice, we returned them only once, they should still
1198 // be in-use.
1199 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1200 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
1203 EXPECT_EQ(0u, returned_to_child.size());
1205 // Transfer resources back from the parent to the child. Set no resources as
1206 // being in use.
1207 ResourceProvider::ResourceIdSet no_resources;
1208 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
1210 ASSERT_EQ(3u, returned_to_child.size());
1211 EXPECT_EQ(0u, returned_to_child[0].sync_point);
1212 EXPECT_EQ(0u, returned_to_child[1].sync_point);
1213 EXPECT_EQ(0u, returned_to_child[2].sync_point);
1214 std::set<ResourceId> expected_ids;
1215 expected_ids.insert(id1);
1216 expected_ids.insert(id2);
1217 expected_ids.insert(id3);
1218 std::set<ResourceId> returned_ids;
1219 for (unsigned i = 0; i < 3; i++)
1220 returned_ids.insert(returned_to_child[i].id);
1221 EXPECT_EQ(expected_ids, returned_ids);
1222 EXPECT_FALSE(returned_to_child[0].lost);
1223 EXPECT_FALSE(returned_to_child[1].lost);
1224 EXPECT_FALSE(returned_to_child[2].lost);
1225 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
1226 returned_to_child.clear();
1228 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id1));
1229 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id2));
1230 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id3));
1233 ResourceProvider::ScopedReadLockSoftware lock(
1234 child_resource_provider_.get(), id1);
1235 const SkBitmap* sk_bitmap = lock.sk_bitmap();
1236 EXPECT_EQ(sk_bitmap->width(), size.width());
1237 EXPECT_EQ(sk_bitmap->height(), size.height());
1238 EXPECT_EQ(0, memcmp(data1, sk_bitmap->getPixels(), pixel_size));
1241 ResourceProvider::ScopedReadLockSoftware lock(
1242 child_resource_provider_.get(), id2);
1243 const SkBitmap* sk_bitmap = lock.sk_bitmap();
1244 EXPECT_EQ(sk_bitmap->width(), size.width());
1245 EXPECT_EQ(sk_bitmap->height(), size.height());
1246 EXPECT_EQ(0, memcmp(data2, sk_bitmap->getPixels(), pixel_size));
1249 // Transfer resources to the parent again.
1250 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1251 resource_ids_to_transfer.push_back(id1);
1252 resource_ids_to_transfer.push_back(id2);
1253 resource_ids_to_transfer.push_back(id3);
1254 TransferableResourceArray list;
1255 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1256 &list);
1257 ASSERT_EQ(3u, list.size());
1258 EXPECT_EQ(id1, list[0].id);
1259 EXPECT_EQ(id2, list[1].id);
1260 EXPECT_EQ(id3, list[2].id);
1261 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1262 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
1263 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
1264 resource_provider_->ReceiveFromChild(child_id, list);
1265 ResourceProvider::ResourceIdSet resource_ids_to_receive;
1266 resource_ids_to_receive.insert(id1);
1267 resource_ids_to_receive.insert(id2);
1268 resource_ids_to_receive.insert(id3);
1269 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1270 resource_ids_to_receive);
1273 EXPECT_EQ(0u, returned_to_child.size());
1275 EXPECT_EQ(3u, resource_provider_->num_resources());
1276 resource_provider_->DestroyChild(child_id);
1277 EXPECT_EQ(0u, resource_provider_->num_resources());
1279 ASSERT_EQ(3u, returned_to_child.size());
1280 EXPECT_EQ(0u, returned_to_child[0].sync_point);
1281 EXPECT_EQ(0u, returned_to_child[1].sync_point);
1282 EXPECT_EQ(0u, returned_to_child[2].sync_point);
1283 std::set<ResourceId> expected_ids;
1284 expected_ids.insert(id1);
1285 expected_ids.insert(id2);
1286 expected_ids.insert(id3);
1287 std::set<ResourceId> returned_ids;
1288 for (unsigned i = 0; i < 3; i++)
1289 returned_ids.insert(returned_to_child[i].id);
1290 EXPECT_EQ(expected_ids, returned_ids);
1291 EXPECT_FALSE(returned_to_child[0].lost);
1292 EXPECT_FALSE(returned_to_child[1].lost);
1293 EXPECT_FALSE(returned_to_child[2].lost);
1296 TEST_P(ResourceProviderTest, TransferGLToSoftware) {
1297 if (GetParam() != ResourceProvider::RESOURCE_TYPE_BITMAP)
1298 return;
1300 scoped_ptr<ResourceProviderContext> child_context_owned(
1301 ResourceProviderContext::Create(shared_data_.get()));
1303 FakeOutputSurfaceClient child_output_surface_client;
1304 scoped_ptr<OutputSurface> child_output_surface(
1305 FakeOutputSurface::Create3d(child_context_owned.Pass()));
1306 CHECK(child_output_surface->BindToClient(&child_output_surface_client));
1308 scoped_ptr<ResourceProvider> child_resource_provider(
1309 ResourceProvider::Create(child_output_surface.get(),
1310 shared_bitmap_manager_.get(),
1311 gpu_memory_buffer_manager_.get(),
1312 NULL,
1314 false,
1315 1));
1317 gfx::Size size(1, 1);
1318 ResourceFormat format = RGBA_8888;
1319 size_t pixel_size = TextureSizeBytes(size, format);
1320 ASSERT_EQ(4U, pixel_size);
1322 ResourceId id1 = child_resource_provider->CreateResource(
1323 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
1324 uint8_t data1[4] = { 1, 2, 3, 4 };
1325 child_resource_provider->CopyToResource(id1, data1, size);
1327 ReturnedResourceArray returned_to_child;
1328 int child_id =
1329 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1331 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1332 resource_ids_to_transfer.push_back(id1);
1333 TransferableResourceArray list;
1334 child_resource_provider->PrepareSendToParent(resource_ids_to_transfer,
1335 &list);
1336 ASSERT_EQ(1u, list.size());
1337 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
1338 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
1339 list[0].mailbox_holder.texture_target);
1340 EXPECT_TRUE(child_resource_provider->InUseByConsumer(id1));
1341 resource_provider_->ReceiveFromChild(child_id, list);
1344 EXPECT_EQ(0u, resource_provider_->num_resources());
1345 ASSERT_EQ(1u, returned_to_child.size());
1346 EXPECT_EQ(returned_to_child[0].id, id1);
1347 ResourceProvider::ResourceIdMap resource_map =
1348 resource_provider_->GetChildToParentMap(child_id);
1349 ResourceId mapped_id1 = resource_map[id1];
1350 EXPECT_EQ(0u, mapped_id1);
1352 resource_provider_->DestroyChild(child_id);
1353 EXPECT_EQ(0u, resource_provider_->num_resources());
1355 ASSERT_EQ(1u, returned_to_child.size());
1356 EXPECT_FALSE(returned_to_child[0].lost);
1359 TEST_P(ResourceProviderTest, TransferInvalidSoftware) {
1360 if (GetParam() != ResourceProvider::RESOURCE_TYPE_BITMAP)
1361 return;
1363 gfx::Size size(1, 1);
1364 ResourceFormat format = RGBA_8888;
1365 size_t pixel_size = TextureSizeBytes(size, format);
1366 ASSERT_EQ(4U, pixel_size);
1368 ResourceId id1 = child_resource_provider_->CreateResource(
1369 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
1370 uint8_t data1[4] = { 1, 2, 3, 4 };
1371 child_resource_provider_->CopyToResource(id1, data1, size);
1373 ReturnedResourceArray returned_to_child;
1374 int child_id =
1375 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1377 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1378 resource_ids_to_transfer.push_back(id1);
1379 TransferableResourceArray list;
1380 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1381 &list);
1382 ASSERT_EQ(1u, list.size());
1383 // Make invalid.
1384 list[0].mailbox_holder.mailbox.name[1] = 5;
1385 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1386 resource_provider_->ReceiveFromChild(child_id, list);
1389 EXPECT_EQ(1u, resource_provider_->num_resources());
1390 EXPECT_EQ(0u, returned_to_child.size());
1392 ResourceProvider::ResourceIdMap resource_map =
1393 resource_provider_->GetChildToParentMap(child_id);
1394 ResourceId mapped_id1 = resource_map[id1];
1395 EXPECT_NE(0u, mapped_id1);
1397 ResourceProvider::ScopedReadLockSoftware lock(resource_provider_.get(),
1398 mapped_id1);
1399 EXPECT_FALSE(lock.valid());
1402 resource_provider_->DestroyChild(child_id);
1403 EXPECT_EQ(0u, resource_provider_->num_resources());
1405 ASSERT_EQ(1u, returned_to_child.size());
1406 EXPECT_FALSE(returned_to_child[0].lost);
1409 TEST_P(ResourceProviderTest, DeleteExportedResources) {
1410 gfx::Size size(1, 1);
1411 ResourceFormat format = RGBA_8888;
1412 size_t pixel_size = TextureSizeBytes(size, format);
1413 ASSERT_EQ(4U, pixel_size);
1415 ResourceId id1 = child_resource_provider_->CreateResource(
1416 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
1417 uint8_t data1[4] = { 1, 2, 3, 4 };
1418 child_resource_provider_->CopyToResource(id1, data1, size);
1420 ResourceId id2 = child_resource_provider_->CreateResource(
1421 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
1422 uint8_t data2[4] = {5, 5, 5, 5};
1423 child_resource_provider_->CopyToResource(id2, data2, size);
1425 ReturnedResourceArray returned_to_child;
1426 int child_id =
1427 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1429 // Transfer some resources to the parent.
1430 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1431 resource_ids_to_transfer.push_back(id1);
1432 resource_ids_to_transfer.push_back(id2);
1433 TransferableResourceArray list;
1434 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1435 &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(child_resource_provider_->InUseByConsumer(id1));
1442 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
1443 resource_provider_->ReceiveFromChild(child_id, list);
1444 ResourceProvider::ResourceIdSet resource_ids_to_receive;
1445 resource_ids_to_receive.insert(id1);
1446 resource_ids_to_receive.insert(id2);
1447 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1448 resource_ids_to_receive);
1451 EXPECT_EQ(2u, resource_provider_->num_resources());
1452 ResourceProvider::ResourceIdMap resource_map =
1453 resource_provider_->GetChildToParentMap(child_id);
1454 ResourceId mapped_id1 = resource_map[id1];
1455 ResourceId mapped_id2 = resource_map[id2];
1456 EXPECT_NE(0u, mapped_id1);
1457 EXPECT_NE(0u, mapped_id2);
1458 EXPECT_FALSE(resource_provider_->InUseByConsumer(id1));
1459 EXPECT_FALSE(resource_provider_->InUseByConsumer(id2));
1462 // The parent transfers the resources to the grandparent.
1463 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1464 resource_ids_to_transfer.push_back(mapped_id1);
1465 resource_ids_to_transfer.push_back(mapped_id2);
1466 TransferableResourceArray list;
1467 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
1469 ASSERT_EQ(2u, list.size());
1470 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) {
1471 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
1472 EXPECT_NE(0u, list[1].mailbox_holder.sync_point);
1474 EXPECT_TRUE(resource_provider_->InUseByConsumer(id1));
1475 EXPECT_TRUE(resource_provider_->InUseByConsumer(id2));
1477 // Release the resource in the parent. Set no resources as being in use. The
1478 // resources are exported so that can't be transferred back yet.
1479 ResourceProvider::ResourceIdSet no_resources;
1480 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
1482 EXPECT_EQ(0u, returned_to_child.size());
1483 EXPECT_EQ(2u, resource_provider_->num_resources());
1485 // Return the resources from the grandparent to the parent. They should be
1486 // returned to the child then.
1487 EXPECT_EQ(2u, list.size());
1488 EXPECT_EQ(mapped_id1, list[0].id);
1489 EXPECT_EQ(mapped_id2, list[1].id);
1490 ReturnedResourceArray returned;
1491 TransferableResource::ReturnResources(list, &returned);
1492 resource_provider_->ReceiveReturnsFromParent(returned);
1494 EXPECT_EQ(0u, resource_provider_->num_resources());
1495 ASSERT_EQ(2u, returned_to_child.size());
1496 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) {
1497 EXPECT_NE(0u, returned_to_child[0].sync_point);
1498 EXPECT_NE(0u, returned_to_child[1].sync_point);
1500 EXPECT_FALSE(returned_to_child[0].lost);
1501 EXPECT_FALSE(returned_to_child[1].lost);
1505 TEST_P(ResourceProviderTest, DestroyChildWithExportedResources) {
1506 gfx::Size size(1, 1);
1507 ResourceFormat format = RGBA_8888;
1508 size_t pixel_size = TextureSizeBytes(size, format);
1509 ASSERT_EQ(4U, pixel_size);
1511 ResourceId id1 = child_resource_provider_->CreateResource(
1512 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
1513 uint8_t data1[4] = {1, 2, 3, 4};
1514 child_resource_provider_->CopyToResource(id1, data1, size);
1516 ResourceId id2 = child_resource_provider_->CreateResource(
1517 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
1518 uint8_t data2[4] = {5, 5, 5, 5};
1519 child_resource_provider_->CopyToResource(id2, data2, size);
1521 ReturnedResourceArray returned_to_child;
1522 int child_id =
1523 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1525 // Transfer some resources to the parent.
1526 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1527 resource_ids_to_transfer.push_back(id1);
1528 resource_ids_to_transfer.push_back(id2);
1529 TransferableResourceArray list;
1530 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1531 &list);
1532 ASSERT_EQ(2u, list.size());
1533 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) {
1534 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
1535 EXPECT_NE(0u, list[1].mailbox_holder.sync_point);
1537 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1538 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
1539 resource_provider_->ReceiveFromChild(child_id, list);
1540 ResourceProvider::ResourceIdSet resource_ids_to_receive;
1541 resource_ids_to_receive.insert(id1);
1542 resource_ids_to_receive.insert(id2);
1543 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1544 resource_ids_to_receive);
1547 EXPECT_EQ(2u, resource_provider_->num_resources());
1548 ResourceProvider::ResourceIdMap resource_map =
1549 resource_provider_->GetChildToParentMap(child_id);
1550 ResourceId mapped_id1 = resource_map[id1];
1551 ResourceId mapped_id2 = resource_map[id2];
1552 EXPECT_NE(0u, mapped_id1);
1553 EXPECT_NE(0u, mapped_id2);
1554 EXPECT_FALSE(resource_provider_->InUseByConsumer(id1));
1555 EXPECT_FALSE(resource_provider_->InUseByConsumer(id2));
1558 // The parent transfers the resources to the grandparent.
1559 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1560 resource_ids_to_transfer.push_back(mapped_id1);
1561 resource_ids_to_transfer.push_back(mapped_id2);
1562 TransferableResourceArray list;
1563 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
1565 ASSERT_EQ(2u, list.size());
1566 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) {
1567 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
1568 EXPECT_NE(0u, list[1].mailbox_holder.sync_point);
1570 EXPECT_TRUE(resource_provider_->InUseByConsumer(id1));
1571 EXPECT_TRUE(resource_provider_->InUseByConsumer(id2));
1573 // Release the resource in the parent. Set no resources as being in use. The
1574 // resources are exported so that can't be transferred back yet.
1575 ResourceProvider::ResourceIdSet no_resources;
1576 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
1578 // Destroy the child, the resources should not be returned yet.
1579 EXPECT_EQ(0u, returned_to_child.size());
1580 EXPECT_EQ(2u, resource_provider_->num_resources());
1582 resource_provider_->DestroyChild(child_id);
1584 EXPECT_EQ(2u, resource_provider_->num_resources());
1585 ASSERT_EQ(0u, returned_to_child.size());
1587 // Return a resource from the grandparent, it should be returned at this
1588 // point.
1589 EXPECT_EQ(2u, list.size());
1590 EXPECT_EQ(mapped_id1, list[0].id);
1591 EXPECT_EQ(mapped_id2, list[1].id);
1592 TransferableResourceArray return_list;
1593 return_list.push_back(list[1]);
1594 list.pop_back();
1595 ReturnedResourceArray returned;
1596 TransferableResource::ReturnResources(return_list, &returned);
1597 resource_provider_->ReceiveReturnsFromParent(returned);
1599 EXPECT_EQ(1u, resource_provider_->num_resources());
1600 ASSERT_EQ(1u, returned_to_child.size());
1601 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) {
1602 EXPECT_NE(0u, returned_to_child[0].sync_point);
1604 EXPECT_FALSE(returned_to_child[0].lost);
1605 returned_to_child.clear();
1607 // Destroy the parent resource provider. The resource that's left should be
1608 // lost at this point, and returned.
1609 resource_provider_ = nullptr;
1610 ASSERT_EQ(1u, returned_to_child.size());
1611 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) {
1612 EXPECT_NE(0u, returned_to_child[0].sync_point);
1614 EXPECT_TRUE(returned_to_child[0].lost);
1618 TEST_P(ResourceProviderTest, DeleteTransferredResources) {
1619 gfx::Size size(1, 1);
1620 ResourceFormat format = RGBA_8888;
1621 size_t pixel_size = TextureSizeBytes(size, format);
1622 ASSERT_EQ(4U, pixel_size);
1624 ResourceId id = child_resource_provider_->CreateResource(
1625 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
1626 uint8_t data[4] = { 1, 2, 3, 4 };
1627 child_resource_provider_->CopyToResource(id, data, size);
1629 ReturnedResourceArray returned_to_child;
1630 int child_id =
1631 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1633 // Transfer some resource to the parent.
1634 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1635 resource_ids_to_transfer.push_back(id);
1636 TransferableResourceArray list;
1637 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1638 &list);
1639 ASSERT_EQ(1u, list.size());
1640 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
1641 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
1642 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id));
1643 resource_provider_->ReceiveFromChild(child_id, list);
1644 ResourceProvider::ResourceIdSet resource_ids_to_receive;
1645 resource_ids_to_receive.insert(id);
1646 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1647 resource_ids_to_receive);
1650 // Delete textures in the child, while they are transfered.
1651 child_resource_provider_->DeleteResource(id);
1652 EXPECT_EQ(1u, child_resource_provider_->num_resources());
1654 EXPECT_EQ(0u, returned_to_child.size());
1656 // Transfer resources back from the parent to the child. Set no resources as
1657 // being in use.
1658 ResourceProvider::ResourceIdSet no_resources;
1659 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
1661 ASSERT_EQ(1u, returned_to_child.size());
1662 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
1663 EXPECT_NE(0u, returned_to_child[0].sync_point);
1664 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
1666 EXPECT_EQ(0u, child_resource_provider_->num_resources());
1669 TEST_P(ResourceProviderTest, UnuseTransferredResources) {
1670 gfx::Size size(1, 1);
1671 ResourceFormat format = RGBA_8888;
1672 size_t pixel_size = TextureSizeBytes(size, format);
1673 ASSERT_EQ(4U, pixel_size);
1675 ResourceId id = child_resource_provider_->CreateResource(
1676 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
1677 uint8_t data[4] = {1, 2, 3, 4};
1678 child_resource_provider_->CopyToResource(id, data, size);
1680 ReturnedResourceArray returned_to_child;
1681 int child_id =
1682 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1683 const ResourceProvider::ResourceIdMap& map =
1684 resource_provider_->GetChildToParentMap(child_id);
1686 // Transfer some resource to the parent.
1687 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1688 resource_ids_to_transfer.push_back(id);
1689 TransferableResourceArray list;
1690 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1691 &list);
1692 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id));
1693 resource_provider_->ReceiveFromChild(child_id, list);
1694 ResourceProvider::ResourceIdSet resource_ids_to_receive;
1695 resource_ids_to_receive.insert(id);
1696 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1697 resource_ids_to_receive);
1699 TransferableResourceArray sent_to_top_level;
1701 // Parent transfers to top-level.
1702 ASSERT_TRUE(map.find(id) != map.end());
1703 ResourceId parent_id = map.find(id)->second;
1704 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1705 resource_ids_to_transfer.push_back(parent_id);
1706 resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1707 &sent_to_top_level);
1708 EXPECT_TRUE(resource_provider_->InUseByConsumer(parent_id));
1711 // Stop using resource.
1712 ResourceProvider::ResourceIdSet empty;
1713 resource_provider_->DeclareUsedResourcesFromChild(child_id, empty);
1714 // Resource is not yet returned to the child, since it's in use by the
1715 // top-level.
1716 EXPECT_TRUE(returned_to_child.empty());
1719 // Send the resource to the parent again.
1720 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1721 resource_ids_to_transfer.push_back(id);
1722 TransferableResourceArray list;
1723 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1724 &list);
1725 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id));
1726 resource_provider_->ReceiveFromChild(child_id, list);
1727 ResourceProvider::ResourceIdSet resource_ids_to_receive;
1728 resource_ids_to_receive.insert(id);
1729 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1730 resource_ids_to_receive);
1733 // Receive returns back from top-level.
1734 ReturnedResourceArray returned;
1735 TransferableResource::ReturnResources(sent_to_top_level, &returned);
1736 resource_provider_->ReceiveReturnsFromParent(returned);
1737 // Resource is still not yet returned to the child, since it's declared used
1738 // in the parent.
1739 EXPECT_TRUE(returned_to_child.empty());
1740 ASSERT_TRUE(map.find(id) != map.end());
1741 ResourceId parent_id = map.find(id)->second;
1742 EXPECT_FALSE(resource_provider_->InUseByConsumer(parent_id));
1745 sent_to_top_level.clear();
1746 // Parent transfers again to top-level.
1747 ASSERT_TRUE(map.find(id) != map.end());
1748 ResourceId parent_id = map.find(id)->second;
1749 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1750 resource_ids_to_transfer.push_back(parent_id);
1751 resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1752 &sent_to_top_level);
1753 EXPECT_TRUE(resource_provider_->InUseByConsumer(parent_id));
1756 // Receive returns back from top-level.
1757 ReturnedResourceArray returned;
1758 TransferableResource::ReturnResources(sent_to_top_level, &returned);
1759 resource_provider_->ReceiveReturnsFromParent(returned);
1760 // Resource is still not yet returned to the child, since it's still
1761 // declared used in the parent.
1762 EXPECT_TRUE(returned_to_child.empty());
1763 ASSERT_TRUE(map.find(id) != map.end());
1764 ResourceId parent_id = map.find(id)->second;
1765 EXPECT_FALSE(resource_provider_->InUseByConsumer(parent_id));
1768 // Stop using resource.
1769 ResourceProvider::ResourceIdSet empty;
1770 resource_provider_->DeclareUsedResourcesFromChild(child_id, empty);
1771 // Resource should have been returned to the child, since it's no longer in
1772 // use by the top-level.
1773 ASSERT_EQ(1u, returned_to_child.size());
1774 EXPECT_EQ(id, returned_to_child[0].id);
1775 EXPECT_EQ(2, returned_to_child[0].count);
1776 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
1777 returned_to_child.clear();
1778 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id));
1782 class ResourceProviderTestTextureFilters : public ResourceProviderTest {
1783 public:
1784 static void RunTest(GLenum child_filter, GLenum parent_filter) {
1785 scoped_ptr<TextureStateTrackingContext> child_context_owned(
1786 new TextureStateTrackingContext);
1787 TextureStateTrackingContext* child_context = child_context_owned.get();
1789 FakeOutputSurfaceClient child_output_surface_client;
1790 scoped_ptr<OutputSurface> child_output_surface(
1791 FakeOutputSurface::Create3d(child_context_owned.Pass()));
1792 CHECK(child_output_surface->BindToClient(&child_output_surface_client));
1793 scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
1794 new TestSharedBitmapManager());
1796 scoped_ptr<ResourceProvider> child_resource_provider(
1797 ResourceProvider::Create(child_output_surface.get(),
1798 shared_bitmap_manager.get(),
1799 NULL,
1800 NULL,
1802 false,
1803 1));
1805 scoped_ptr<TextureStateTrackingContext> parent_context_owned(
1806 new TextureStateTrackingContext);
1807 TextureStateTrackingContext* parent_context = parent_context_owned.get();
1809 FakeOutputSurfaceClient parent_output_surface_client;
1810 scoped_ptr<OutputSurface> parent_output_surface(
1811 FakeOutputSurface::Create3d(parent_context_owned.Pass()));
1812 CHECK(parent_output_surface->BindToClient(&parent_output_surface_client));
1814 scoped_ptr<ResourceProvider> parent_resource_provider(
1815 ResourceProvider::Create(parent_output_surface.get(),
1816 shared_bitmap_manager.get(),
1817 NULL,
1818 NULL,
1820 false,
1821 1));
1823 gfx::Size size(1, 1);
1824 ResourceFormat format = RGBA_8888;
1825 int child_texture_id = 1;
1826 int parent_texture_id = 2;
1828 size_t pixel_size = TextureSizeBytes(size, format);
1829 ASSERT_EQ(4U, pixel_size);
1831 ResourceId id = child_resource_provider->CreateResource(
1832 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE,
1833 format);
1835 // The new texture is created with GL_LINEAR.
1836 EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, child_texture_id))
1837 .Times(2); // Once to create and once to allocate.
1838 EXPECT_CALL(*child_context,
1839 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
1840 EXPECT_CALL(*child_context,
1841 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
1842 EXPECT_CALL(
1843 *child_context,
1844 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
1845 EXPECT_CALL(
1846 *child_context,
1847 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
1848 EXPECT_CALL(*child_context,
1849 texParameteri(GL_TEXTURE_2D,
1850 GL_TEXTURE_POOL_CHROMIUM,
1851 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM));
1852 child_resource_provider->AllocateForTesting(id);
1853 Mock::VerifyAndClearExpectations(child_context);
1855 uint8_t data[4] = { 1, 2, 3, 4 };
1857 EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, child_texture_id));
1858 child_resource_provider->CopyToResource(id, data, size);
1859 Mock::VerifyAndClearExpectations(child_context);
1861 // The texture is set to |child_filter| in the child.
1862 EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, child_texture_id));
1863 if (child_filter != GL_LINEAR) {
1864 EXPECT_CALL(
1865 *child_context,
1866 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, child_filter));
1867 EXPECT_CALL(
1868 *child_context,
1869 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, child_filter));
1871 SetResourceFilter(child_resource_provider.get(), id, child_filter);
1872 Mock::VerifyAndClearExpectations(child_context);
1874 ReturnedResourceArray returned_to_child;
1875 int child_id = parent_resource_provider->CreateChild(
1876 GetReturnCallback(&returned_to_child));
1878 // Transfer some resource to the parent.
1879 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1880 resource_ids_to_transfer.push_back(id);
1881 TransferableResourceArray list;
1883 EXPECT_CALL(*child_context,
1884 produceTextureDirectCHROMIUM(_, GL_TEXTURE_2D, _));
1885 EXPECT_CALL(*child_context, insertSyncPoint());
1886 child_resource_provider->PrepareSendToParent(resource_ids_to_transfer,
1887 &list);
1888 Mock::VerifyAndClearExpectations(child_context);
1890 ASSERT_EQ(1u, list.size());
1891 EXPECT_EQ(static_cast<unsigned>(child_filter), list[0].filter);
1893 EXPECT_CALL(*parent_context,
1894 createAndConsumeTextureCHROMIUM(GL_TEXTURE_2D, _))
1895 .WillOnce(Return(parent_texture_id));
1897 parent_resource_provider->ReceiveFromChild(child_id, list);
1899 parent_resource_provider->WaitSyncPointIfNeeded(list[0].id);
1900 ResourceProvider::ScopedReadLockGL lock(parent_resource_provider.get(),
1901 list[0].id);
1903 Mock::VerifyAndClearExpectations(parent_context);
1905 ResourceProvider::ResourceIdSet resource_ids_to_receive;
1906 resource_ids_to_receive.insert(id);
1907 parent_resource_provider->DeclareUsedResourcesFromChild(
1908 child_id, resource_ids_to_receive);
1909 Mock::VerifyAndClearExpectations(parent_context);
1911 ResourceProvider::ResourceIdMap resource_map =
1912 parent_resource_provider->GetChildToParentMap(child_id);
1913 ResourceId mapped_id = resource_map[id];
1914 EXPECT_NE(0u, mapped_id);
1916 // The texture is set to |parent_filter| in the parent.
1917 EXPECT_CALL(*parent_context, bindTexture(GL_TEXTURE_2D, parent_texture_id));
1918 EXPECT_CALL(
1919 *parent_context,
1920 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, parent_filter));
1921 EXPECT_CALL(
1922 *parent_context,
1923 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, parent_filter));
1924 SetResourceFilter(parent_resource_provider.get(), mapped_id, parent_filter);
1925 Mock::VerifyAndClearExpectations(parent_context);
1927 // The texture should be reset to |child_filter| in the parent when it is
1928 // returned, since that is how it was received.
1929 EXPECT_CALL(*parent_context, bindTexture(GL_TEXTURE_2D, parent_texture_id));
1930 EXPECT_CALL(
1931 *parent_context,
1932 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, child_filter));
1933 EXPECT_CALL(
1934 *parent_context,
1935 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, child_filter));
1938 EXPECT_EQ(0u, returned_to_child.size());
1940 // Transfer resources back from the parent to the child. Set no resources
1941 // as being in use.
1942 ResourceProvider::ResourceIdSet no_resources;
1943 EXPECT_CALL(*parent_context, insertSyncPoint());
1944 parent_resource_provider->DeclareUsedResourcesFromChild(child_id,
1945 no_resources);
1946 Mock::VerifyAndClearExpectations(parent_context);
1948 ASSERT_EQ(1u, returned_to_child.size());
1949 child_resource_provider->ReceiveReturnsFromParent(returned_to_child);
1952 // The child remembers the texture filter is set to |child_filter|.
1953 EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, child_texture_id));
1954 SetResourceFilter(child_resource_provider.get(), id, child_filter);
1955 Mock::VerifyAndClearExpectations(child_context);
1959 TEST_P(ResourceProviderTest, TextureFilters_ChildNearestParentLinear) {
1960 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
1961 return;
1962 ResourceProviderTestTextureFilters::RunTest(GL_NEAREST, GL_LINEAR);
1965 TEST_P(ResourceProviderTest, TextureFilters_ChildLinearParentNearest) {
1966 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
1967 return;
1968 ResourceProviderTestTextureFilters::RunTest(GL_LINEAR, GL_NEAREST);
1971 TEST_P(ResourceProviderTest, TransferMailboxResources) {
1972 // Other mailbox transfers tested elsewhere.
1973 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
1974 return;
1975 unsigned texture = context()->createTexture();
1976 context()->bindTexture(GL_TEXTURE_2D, texture);
1977 uint8_t data[4] = { 1, 2, 3, 4 };
1978 context()->texImage2D(
1979 GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &data);
1980 gpu::Mailbox mailbox;
1981 context()->genMailboxCHROMIUM(mailbox.name);
1982 context()->produceTextureDirectCHROMIUM(texture, GL_TEXTURE_2D, mailbox.name);
1983 uint32 sync_point = context()->insertSyncPoint();
1985 // All the logic below assumes that the sync points are all positive.
1986 EXPECT_LT(0u, sync_point);
1988 uint32 release_sync_point = 0;
1989 bool lost_resource = false;
1990 BlockingTaskRunner* main_thread_task_runner = NULL;
1991 ReleaseCallbackImpl callback = base::Bind(ReleaseCallback,
1992 &release_sync_point,
1993 &lost_resource,
1994 &main_thread_task_runner);
1995 ResourceId resource = resource_provider_->CreateResourceFromTextureMailbox(
1996 TextureMailbox(mailbox, GL_TEXTURE_2D, sync_point),
1997 SingleReleaseCallbackImpl::Create(callback));
1998 EXPECT_EQ(1u, context()->NumTextures());
1999 EXPECT_EQ(0u, release_sync_point);
2001 // Transfer the resource, expect the sync points to be consistent.
2002 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2003 resource_ids_to_transfer.push_back(resource);
2004 TransferableResourceArray list;
2005 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
2006 ASSERT_EQ(1u, list.size());
2007 EXPECT_LE(sync_point, list[0].mailbox_holder.sync_point);
2008 EXPECT_EQ(0,
2009 memcmp(mailbox.name,
2010 list[0].mailbox_holder.mailbox.name,
2011 sizeof(mailbox.name)));
2012 EXPECT_EQ(0u, release_sync_point);
2014 context()->waitSyncPoint(list[0].mailbox_holder.sync_point);
2015 unsigned other_texture =
2016 context()->createAndConsumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
2017 uint8_t test_data[4] = { 0 };
2018 context()->GetPixels(
2019 gfx::Size(1, 1), RGBA_8888, test_data);
2020 EXPECT_EQ(0, memcmp(data, test_data, sizeof(data)));
2022 context()->produceTextureDirectCHROMIUM(other_texture, GL_TEXTURE_2D,
2023 mailbox.name);
2024 context()->deleteTexture(other_texture);
2025 list[0].mailbox_holder.sync_point = context()->insertSyncPoint();
2026 EXPECT_LT(0u, list[0].mailbox_holder.sync_point);
2028 // Receive the resource, then delete it, expect the sync points to be
2029 // consistent.
2030 ReturnedResourceArray returned;
2031 TransferableResource::ReturnResources(list, &returned);
2032 resource_provider_->ReceiveReturnsFromParent(returned);
2033 EXPECT_EQ(1u, context()->NumTextures());
2034 EXPECT_EQ(0u, release_sync_point);
2036 resource_provider_->DeleteResource(resource);
2037 EXPECT_LE(list[0].mailbox_holder.sync_point, release_sync_point);
2038 EXPECT_FALSE(lost_resource);
2039 EXPECT_EQ(main_thread_task_runner_.get(), main_thread_task_runner);
2042 // We're going to do the same thing as above, but testing the case where we
2043 // delete the resource before we receive it back.
2044 sync_point = release_sync_point;
2045 EXPECT_LT(0u, sync_point);
2046 release_sync_point = 0;
2047 resource = resource_provider_->CreateResourceFromTextureMailbox(
2048 TextureMailbox(mailbox, GL_TEXTURE_2D, sync_point),
2049 SingleReleaseCallbackImpl::Create(callback));
2050 EXPECT_EQ(1u, context()->NumTextures());
2051 EXPECT_EQ(0u, release_sync_point);
2053 // Transfer the resource, expect the sync points to be consistent.
2054 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2055 resource_ids_to_transfer.push_back(resource);
2056 TransferableResourceArray list;
2057 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
2058 ASSERT_EQ(1u, list.size());
2059 EXPECT_LE(sync_point, list[0].mailbox_holder.sync_point);
2060 EXPECT_EQ(0,
2061 memcmp(mailbox.name,
2062 list[0].mailbox_holder.mailbox.name,
2063 sizeof(mailbox.name)));
2064 EXPECT_EQ(0u, release_sync_point);
2066 context()->waitSyncPoint(list[0].mailbox_holder.sync_point);
2067 unsigned other_texture =
2068 context()->createAndConsumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
2069 uint8_t test_data[4] = { 0 };
2070 context()->GetPixels(
2071 gfx::Size(1, 1), RGBA_8888, test_data);
2072 EXPECT_EQ(0, memcmp(data, test_data, sizeof(data)));
2074 context()->produceTextureDirectCHROMIUM(other_texture, GL_TEXTURE_2D,
2075 mailbox.name);
2076 context()->deleteTexture(other_texture);
2077 list[0].mailbox_holder.sync_point = context()->insertSyncPoint();
2078 EXPECT_LT(0u, list[0].mailbox_holder.sync_point);
2080 // Delete the resource, which shouldn't do anything.
2081 resource_provider_->DeleteResource(resource);
2082 EXPECT_EQ(1u, context()->NumTextures());
2083 EXPECT_EQ(0u, release_sync_point);
2085 // Then receive the resource which should release the mailbox, expect the
2086 // sync points to be consistent.
2087 ReturnedResourceArray returned;
2088 TransferableResource::ReturnResources(list, &returned);
2089 resource_provider_->ReceiveReturnsFromParent(returned);
2090 EXPECT_LE(list[0].mailbox_holder.sync_point, release_sync_point);
2091 EXPECT_FALSE(lost_resource);
2092 EXPECT_EQ(main_thread_task_runner_.get(), main_thread_task_runner);
2095 context()->waitSyncPoint(release_sync_point);
2096 texture =
2097 context()->createAndConsumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
2098 context()->deleteTexture(texture);
2101 TEST_P(ResourceProviderTest, LostResourceInParent) {
2102 gfx::Size size(1, 1);
2103 ResourceFormat format = RGBA_8888;
2104 ResourceId resource = child_resource_provider_->CreateResource(
2105 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
2106 child_resource_provider_->AllocateForTesting(resource);
2107 // Expect a GL resource to be lost.
2108 bool should_lose_resource =
2109 GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE;
2111 ReturnedResourceArray returned_to_child;
2112 int child_id =
2113 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
2115 // Transfer the resource to the parent.
2116 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2117 resource_ids_to_transfer.push_back(resource);
2118 TransferableResourceArray list;
2119 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
2120 &list);
2121 EXPECT_EQ(1u, list.size());
2123 resource_provider_->ReceiveFromChild(child_id, list);
2124 ResourceProvider::ResourceIdSet resource_ids_to_receive;
2125 resource_ids_to_receive.insert(resource);
2126 resource_provider_->DeclareUsedResourcesFromChild(child_id,
2127 resource_ids_to_receive);
2130 // Lose the output surface in the parent.
2131 resource_provider_->DidLoseOutputSurface();
2134 EXPECT_EQ(0u, returned_to_child.size());
2136 // Transfer resources back from the parent to the child. Set no resources as
2137 // being in use.
2138 ResourceProvider::ResourceIdSet no_resources;
2139 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
2141 // Expect a GL resource to be lost.
2142 ASSERT_EQ(1u, returned_to_child.size());
2143 EXPECT_EQ(should_lose_resource, returned_to_child[0].lost);
2144 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
2145 returned_to_child.clear();
2148 // A GL resource should be lost.
2149 EXPECT_EQ(should_lose_resource, child_resource_provider_->IsLost(resource));
2151 // Lost resources stay in use in the parent forever.
2152 EXPECT_EQ(should_lose_resource,
2153 child_resource_provider_->InUseByConsumer(resource));
2156 TEST_P(ResourceProviderTest, LostResourceInGrandParent) {
2157 gfx::Size size(1, 1);
2158 ResourceFormat format = RGBA_8888;
2159 ResourceId resource = child_resource_provider_->CreateResource(
2160 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
2161 child_resource_provider_->AllocateForTesting(resource);
2163 ReturnedResourceArray returned_to_child;
2164 int child_id =
2165 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
2167 // Transfer the resource to the parent.
2168 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2169 resource_ids_to_transfer.push_back(resource);
2170 TransferableResourceArray list;
2171 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
2172 &list);
2173 EXPECT_EQ(1u, list.size());
2175 resource_provider_->ReceiveFromChild(child_id, list);
2176 ResourceProvider::ResourceIdSet resource_ids_to_receive;
2177 resource_ids_to_receive.insert(resource);
2178 resource_provider_->DeclareUsedResourcesFromChild(child_id,
2179 resource_ids_to_receive);
2183 ResourceProvider::ResourceIdMap resource_map =
2184 resource_provider_->GetChildToParentMap(child_id);
2185 ResourceId parent_resource = resource_map[resource];
2186 EXPECT_NE(0u, parent_resource);
2188 // Transfer to a grandparent.
2189 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2190 resource_ids_to_transfer.push_back(parent_resource);
2191 TransferableResourceArray list;
2192 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
2194 // Receive back a lost resource from the grandparent.
2195 EXPECT_EQ(1u, list.size());
2196 EXPECT_EQ(parent_resource, list[0].id);
2197 ReturnedResourceArray returned;
2198 TransferableResource::ReturnResources(list, &returned);
2199 EXPECT_EQ(1u, returned.size());
2200 EXPECT_EQ(parent_resource, returned[0].id);
2201 returned[0].lost = true;
2202 resource_provider_->ReceiveReturnsFromParent(returned);
2204 // The resource should be lost.
2205 EXPECT_TRUE(resource_provider_->IsLost(parent_resource));
2207 // Lost resources stay in use in the parent forever.
2208 EXPECT_TRUE(resource_provider_->InUseByConsumer(parent_resource));
2212 EXPECT_EQ(0u, returned_to_child.size());
2214 // Transfer resources back from the parent to the child. Set no resources as
2215 // being in use.
2216 ResourceProvider::ResourceIdSet no_resources;
2217 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
2219 // Expect the resource to be lost.
2220 ASSERT_EQ(1u, returned_to_child.size());
2221 EXPECT_TRUE(returned_to_child[0].lost);
2222 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
2223 returned_to_child.clear();
2226 // The resource should be lost.
2227 EXPECT_TRUE(child_resource_provider_->IsLost(resource));
2229 // Lost resources stay in use in the parent forever.
2230 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(resource));
2233 TEST_P(ResourceProviderTest, LostMailboxInParent) {
2234 uint32 release_sync_point = 0;
2235 bool lost_resource = false;
2236 bool release_called = false;
2237 uint32 sync_point = 0;
2238 ResourceId resource = CreateChildMailbox(&release_sync_point, &lost_resource,
2239 &release_called, &sync_point);
2241 ReturnedResourceArray returned_to_child;
2242 int child_id =
2243 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
2245 // Transfer the resource to the parent.
2246 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2247 resource_ids_to_transfer.push_back(resource);
2248 TransferableResourceArray list;
2249 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
2250 &list);
2251 EXPECT_EQ(1u, list.size());
2253 resource_provider_->ReceiveFromChild(child_id, list);
2254 ResourceProvider::ResourceIdSet resource_ids_to_receive;
2255 resource_ids_to_receive.insert(resource);
2256 resource_provider_->DeclareUsedResourcesFromChild(child_id,
2257 resource_ids_to_receive);
2260 // Lose the output surface in the parent.
2261 resource_provider_->DidLoseOutputSurface();
2264 EXPECT_EQ(0u, returned_to_child.size());
2266 // Transfer resources back from the parent to the child. Set no resources as
2267 // being in use.
2268 ResourceProvider::ResourceIdSet no_resources;
2269 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
2271 ASSERT_EQ(1u, returned_to_child.size());
2272 // Losing an output surface only loses hardware resources.
2273 EXPECT_EQ(returned_to_child[0].lost,
2274 GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE);
2275 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
2276 returned_to_child.clear();
2279 // Delete the resource in the child. Expect the resource to be lost if it's
2280 // a GL texture.
2281 child_resource_provider_->DeleteResource(resource);
2282 EXPECT_EQ(lost_resource,
2283 GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE);
2286 TEST_P(ResourceProviderTest, LostMailboxInGrandParent) {
2287 uint32 release_sync_point = 0;
2288 bool lost_resource = false;
2289 bool release_called = false;
2290 uint32 sync_point = 0;
2291 ResourceId resource = CreateChildMailbox(&release_sync_point, &lost_resource,
2292 &release_called, &sync_point);
2294 ReturnedResourceArray returned_to_child;
2295 int child_id =
2296 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
2298 // Transfer the resource to the parent.
2299 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2300 resource_ids_to_transfer.push_back(resource);
2301 TransferableResourceArray list;
2302 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
2303 &list);
2304 EXPECT_EQ(1u, list.size());
2306 resource_provider_->ReceiveFromChild(child_id, list);
2307 ResourceProvider::ResourceIdSet resource_ids_to_receive;
2308 resource_ids_to_receive.insert(resource);
2309 resource_provider_->DeclareUsedResourcesFromChild(child_id,
2310 resource_ids_to_receive);
2314 ResourceProvider::ResourceIdMap resource_map =
2315 resource_provider_->GetChildToParentMap(child_id);
2316 ResourceId parent_resource = resource_map[resource];
2317 EXPECT_NE(0u, parent_resource);
2319 // Transfer to a grandparent.
2320 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2321 resource_ids_to_transfer.push_back(parent_resource);
2322 TransferableResourceArray list;
2323 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
2325 // Receive back a lost resource from the grandparent.
2326 EXPECT_EQ(1u, list.size());
2327 EXPECT_EQ(parent_resource, list[0].id);
2328 ReturnedResourceArray returned;
2329 TransferableResource::ReturnResources(list, &returned);
2330 EXPECT_EQ(1u, returned.size());
2331 EXPECT_EQ(parent_resource, returned[0].id);
2332 returned[0].lost = true;
2333 resource_provider_->ReceiveReturnsFromParent(returned);
2337 EXPECT_EQ(0u, returned_to_child.size());
2339 // Transfer resources back from the parent to the child. Set no resources as
2340 // being in use.
2341 ResourceProvider::ResourceIdSet no_resources;
2342 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
2344 // Expect the resource to be lost.
2345 ASSERT_EQ(1u, returned_to_child.size());
2346 EXPECT_TRUE(returned_to_child[0].lost);
2347 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
2348 returned_to_child.clear();
2351 // Delete the resource in the child. Expect the resource to be lost.
2352 child_resource_provider_->DeleteResource(resource);
2353 EXPECT_TRUE(lost_resource);
2356 TEST_P(ResourceProviderTest, Shutdown) {
2357 uint32 release_sync_point = 0;
2358 bool lost_resource = false;
2359 bool release_called = false;
2360 uint32 sync_point = 0;
2361 CreateChildMailbox(
2362 &release_sync_point, &lost_resource, &release_called, &sync_point);
2364 EXPECT_EQ(0u, release_sync_point);
2365 EXPECT_FALSE(lost_resource);
2367 child_resource_provider_ = nullptr;
2369 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) {
2370 EXPECT_LE(sync_point, release_sync_point);
2372 EXPECT_TRUE(release_called);
2373 EXPECT_FALSE(lost_resource);
2376 TEST_P(ResourceProviderTest, ShutdownWithExportedResource) {
2377 uint32 release_sync_point = 0;
2378 bool lost_resource = false;
2379 bool release_called = false;
2380 uint32 sync_point = 0;
2381 ResourceId resource = CreateChildMailbox(&release_sync_point, &lost_resource,
2382 &release_called, &sync_point);
2384 // Transfer the resource, so we can't release it properly on shutdown.
2385 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2386 resource_ids_to_transfer.push_back(resource);
2387 TransferableResourceArray list;
2388 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
2389 &list);
2391 EXPECT_EQ(0u, release_sync_point);
2392 EXPECT_FALSE(lost_resource);
2394 child_resource_provider_ = nullptr;
2396 // Since the resource is in the parent, the child considers it lost.
2397 EXPECT_EQ(0u, release_sync_point);
2398 EXPECT_TRUE(lost_resource);
2401 TEST_P(ResourceProviderTest, LostContext) {
2402 // TextureMailbox callbacks only exist for GL textures for now.
2403 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
2404 return;
2405 unsigned texture = context()->createTexture();
2406 context()->bindTexture(GL_TEXTURE_2D, texture);
2407 gpu::Mailbox mailbox;
2408 context()->genMailboxCHROMIUM(mailbox.name);
2409 context()->produceTextureDirectCHROMIUM(texture, GL_TEXTURE_2D, mailbox.name);
2410 uint32 sync_point = context()->insertSyncPoint();
2412 EXPECT_LT(0u, sync_point);
2414 uint32 release_sync_point = 0;
2415 bool lost_resource = false;
2416 BlockingTaskRunner* main_thread_task_runner = NULL;
2417 scoped_ptr<SingleReleaseCallbackImpl> callback =
2418 SingleReleaseCallbackImpl::Create(base::Bind(ReleaseCallback,
2419 &release_sync_point,
2420 &lost_resource,
2421 &main_thread_task_runner));
2422 resource_provider_->CreateResourceFromTextureMailbox(
2423 TextureMailbox(mailbox, GL_TEXTURE_2D, sync_point), callback.Pass());
2425 EXPECT_EQ(0u, release_sync_point);
2426 EXPECT_FALSE(lost_resource);
2427 EXPECT_EQ(NULL, main_thread_task_runner);
2429 resource_provider_->DidLoseOutputSurface();
2430 resource_provider_ = nullptr;
2432 EXPECT_LE(sync_point, release_sync_point);
2433 EXPECT_TRUE(lost_resource);
2434 EXPECT_EQ(main_thread_task_runner_.get(), main_thread_task_runner);
2437 TEST_P(ResourceProviderTest, ScopedSampler) {
2438 // Sampling is only supported for GL textures.
2439 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
2440 return;
2442 scoped_ptr<TextureStateTrackingContext> context_owned(
2443 new TextureStateTrackingContext);
2444 TextureStateTrackingContext* context = context_owned.get();
2446 FakeOutputSurfaceClient output_surface_client;
2447 scoped_ptr<OutputSurface> output_surface(
2448 FakeOutputSurface::Create3d(context_owned.Pass()));
2449 CHECK(output_surface->BindToClient(&output_surface_client));
2451 scoped_ptr<ResourceProvider> resource_provider(
2452 ResourceProvider::Create(output_surface.get(),
2453 shared_bitmap_manager_.get(),
2454 gpu_memory_buffer_manager_.get(),
2455 NULL,
2457 false,
2458 1));
2460 gfx::Size size(1, 1);
2461 ResourceFormat format = RGBA_8888;
2462 int texture_id = 1;
2464 ResourceId id = resource_provider->CreateResource(
2465 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
2467 // Check that the texture gets created with the right sampler settings.
2468 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id))
2469 .Times(2); // Once to create and once to allocate.
2470 EXPECT_CALL(*context,
2471 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
2472 EXPECT_CALL(*context,
2473 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
2474 EXPECT_CALL(
2475 *context,
2476 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
2477 EXPECT_CALL(
2478 *context,
2479 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
2480 EXPECT_CALL(*context,
2481 texParameteri(GL_TEXTURE_2D,
2482 GL_TEXTURE_POOL_CHROMIUM,
2483 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM));
2485 resource_provider->AllocateForTesting(id);
2486 Mock::VerifyAndClearExpectations(context);
2488 // Creating a sampler with the default filter should not change any texture
2489 // parameters.
2491 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
2492 ResourceProvider::ScopedSamplerGL sampler(
2493 resource_provider.get(), id, GL_TEXTURE_2D, GL_LINEAR);
2494 Mock::VerifyAndClearExpectations(context);
2497 // Using a different filter should be reflected in the texture parameters.
2499 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
2500 EXPECT_CALL(
2501 *context,
2502 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
2503 EXPECT_CALL(
2504 *context,
2505 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
2506 ResourceProvider::ScopedSamplerGL sampler(
2507 resource_provider.get(), id, GL_TEXTURE_2D, GL_NEAREST);
2508 Mock::VerifyAndClearExpectations(context);
2511 // Test resetting to the default filter.
2513 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
2514 EXPECT_CALL(*context,
2515 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
2516 EXPECT_CALL(*context,
2517 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
2518 ResourceProvider::ScopedSamplerGL sampler(
2519 resource_provider.get(), id, GL_TEXTURE_2D, GL_LINEAR);
2520 Mock::VerifyAndClearExpectations(context);
2524 TEST_P(ResourceProviderTest, ManagedResource) {
2525 // Sampling is only supported for GL textures.
2526 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
2527 return;
2529 scoped_ptr<TextureStateTrackingContext> context_owned(
2530 new TextureStateTrackingContext);
2531 TextureStateTrackingContext* context = context_owned.get();
2533 FakeOutputSurfaceClient output_surface_client;
2534 scoped_ptr<OutputSurface> output_surface(
2535 FakeOutputSurface::Create3d(context_owned.Pass()));
2536 CHECK(output_surface->BindToClient(&output_surface_client));
2538 scoped_ptr<ResourceProvider> resource_provider(
2539 ResourceProvider::Create(output_surface.get(),
2540 shared_bitmap_manager_.get(),
2541 gpu_memory_buffer_manager_.get(),
2542 NULL,
2544 false,
2545 1));
2547 gfx::Size size(1, 1);
2548 ResourceFormat format = RGBA_8888;
2549 int texture_id = 1;
2551 // Check that the texture gets created with the right sampler settings.
2552 ResourceId id = resource_provider->CreateManagedResource(
2553 size, GL_TEXTURE_2D, GL_CLAMP_TO_EDGE,
2554 ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
2555 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
2556 EXPECT_CALL(*context,
2557 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
2558 EXPECT_CALL(*context,
2559 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
2560 EXPECT_CALL(
2561 *context,
2562 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
2563 EXPECT_CALL(
2564 *context,
2565 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
2566 EXPECT_CALL(*context,
2567 texParameteri(GL_TEXTURE_2D,
2568 GL_TEXTURE_POOL_CHROMIUM,
2569 GL_TEXTURE_POOL_MANAGED_CHROMIUM));
2570 resource_provider->CreateForTesting(id);
2571 EXPECT_NE(0u, id);
2573 Mock::VerifyAndClearExpectations(context);
2576 TEST_P(ResourceProviderTest, TextureWrapMode) {
2577 // Sampling is only supported for GL textures.
2578 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
2579 return;
2581 scoped_ptr<TextureStateTrackingContext> context_owned(
2582 new TextureStateTrackingContext);
2583 TextureStateTrackingContext* context = context_owned.get();
2585 FakeOutputSurfaceClient output_surface_client;
2586 scoped_ptr<OutputSurface> output_surface(
2587 FakeOutputSurface::Create3d(context_owned.Pass()));
2588 CHECK(output_surface->BindToClient(&output_surface_client));
2590 scoped_ptr<ResourceProvider> resource_provider(
2591 ResourceProvider::Create(output_surface.get(),
2592 shared_bitmap_manager_.get(),
2593 gpu_memory_buffer_manager_.get(),
2594 NULL,
2596 false,
2597 1));
2599 gfx::Size size(1, 1);
2600 ResourceFormat format = RGBA_8888;
2601 GLenum texture_pool = GL_TEXTURE_POOL_UNMANAGED_CHROMIUM;
2603 for (int texture_id = 1; texture_id <= 2; ++texture_id) {
2604 GLint wrap_mode = texture_id == 1 ? GL_CLAMP_TO_EDGE : GL_REPEAT;
2605 // Check that the texture gets created with the right sampler settings.
2606 ResourceId id = resource_provider->CreateGLTexture(
2607 size, GL_TEXTURE_2D, texture_pool, wrap_mode,
2608 ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
2609 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
2610 EXPECT_CALL(*context,
2611 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
2612 EXPECT_CALL(*context,
2613 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
2614 EXPECT_CALL(*context,
2615 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap_mode));
2616 EXPECT_CALL(*context,
2617 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap_mode));
2618 EXPECT_CALL(*context,
2619 texParameteri(GL_TEXTURE_2D,
2620 GL_TEXTURE_POOL_CHROMIUM,
2621 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM));
2622 resource_provider->CreateForTesting(id);
2623 EXPECT_NE(0u, id);
2625 Mock::VerifyAndClearExpectations(context);
2629 TEST_P(ResourceProviderTest, TextureHint) {
2630 // Sampling is only supported for GL textures.
2631 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
2632 return;
2634 scoped_ptr<TextureStateTrackingContext> context_owned(
2635 new TextureStateTrackingContext);
2636 TextureStateTrackingContext* context = context_owned.get();
2637 context->set_support_texture_storage(true);
2638 context->set_support_texture_usage(true);
2640 FakeOutputSurfaceClient output_surface_client;
2641 scoped_ptr<OutputSurface> output_surface(
2642 FakeOutputSurface::Create3d(context_owned.Pass()));
2643 CHECK(output_surface->BindToClient(&output_surface_client));
2645 scoped_ptr<ResourceProvider> resource_provider(
2646 ResourceProvider::Create(output_surface.get(),
2647 shared_bitmap_manager_.get(),
2648 gpu_memory_buffer_manager_.get(),
2649 NULL,
2651 false,
2652 1));
2654 gfx::Size size(1, 1);
2655 ResourceFormat format = RGBA_8888;
2656 GLenum texture_pool = GL_TEXTURE_POOL_UNMANAGED_CHROMIUM;
2658 const ResourceProvider::TextureHint hints[4] = {
2659 ResourceProvider::TEXTURE_HINT_DEFAULT,
2660 ResourceProvider::TEXTURE_HINT_IMMUTABLE,
2661 ResourceProvider::TEXTURE_HINT_FRAMEBUFFER,
2662 ResourceProvider::TEXTURE_HINT_IMMUTABLE_FRAMEBUFFER,
2664 for (GLuint texture_id = 1; texture_id <= arraysize(hints); ++texture_id) {
2665 // Check that the texture gets created with the right sampler settings.
2666 ResourceId id = resource_provider->CreateGLTexture(
2667 size, GL_TEXTURE_2D, texture_pool, GL_CLAMP_TO_EDGE,
2668 hints[texture_id - 1], format);
2669 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
2670 EXPECT_CALL(*context,
2671 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
2672 EXPECT_CALL(*context,
2673 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
2674 EXPECT_CALL(
2675 *context,
2676 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
2677 EXPECT_CALL(
2678 *context,
2679 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
2680 EXPECT_CALL(*context,
2681 texParameteri(GL_TEXTURE_2D,
2682 GL_TEXTURE_POOL_CHROMIUM,
2683 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM));
2684 // Check only TEXTURE_HINT_FRAMEBUFFER set GL_TEXTURE_USAGE_ANGLE.
2685 bool is_framebuffer_hint =
2686 hints[texture_id - 1] & ResourceProvider::TEXTURE_HINT_FRAMEBUFFER;
2687 EXPECT_CALL(*context,
2688 texParameteri(GL_TEXTURE_2D,
2689 GL_TEXTURE_USAGE_ANGLE,
2690 GL_FRAMEBUFFER_ATTACHMENT_ANGLE))
2691 .Times(is_framebuffer_hint ? 1 : 0);
2692 resource_provider->CreateForTesting(id);
2693 EXPECT_NE(0u, id);
2695 Mock::VerifyAndClearExpectations(context);
2699 TEST_P(ResourceProviderTest, TextureMailbox_SharedMemory) {
2700 if (GetParam() != ResourceProvider::RESOURCE_TYPE_BITMAP)
2701 return;
2703 gfx::Size size(64, 64);
2704 const uint32_t kBadBeef = 0xbadbeef;
2705 scoped_ptr<SharedBitmap> shared_bitmap(
2706 CreateAndFillSharedBitmap(shared_bitmap_manager_.get(), size, kBadBeef));
2708 FakeOutputSurfaceClient output_surface_client;
2709 scoped_ptr<OutputSurface> output_surface(
2710 FakeOutputSurface::CreateSoftware(make_scoped_ptr(
2711 new SoftwareOutputDevice)));
2712 CHECK(output_surface->BindToClient(&output_surface_client));
2714 scoped_ptr<ResourceProvider> resource_provider(
2715 ResourceProvider::Create(output_surface.get(),
2716 shared_bitmap_manager_.get(),
2717 gpu_memory_buffer_manager_.get(),
2718 main_thread_task_runner_.get(),
2720 false,
2721 1));
2723 uint32 release_sync_point = 0;
2724 bool lost_resource = false;
2725 BlockingTaskRunner* main_thread_task_runner = NULL;
2726 scoped_ptr<SingleReleaseCallbackImpl> callback =
2727 SingleReleaseCallbackImpl::Create(base::Bind(&ReleaseCallback,
2728 &release_sync_point,
2729 &lost_resource,
2730 &main_thread_task_runner));
2731 TextureMailbox mailbox(shared_bitmap.get(), size);
2733 ResourceId id = resource_provider->CreateResourceFromTextureMailbox(
2734 mailbox, callback.Pass());
2735 EXPECT_NE(0u, id);
2738 ResourceProvider::ScopedReadLockSoftware lock(resource_provider.get(), id);
2739 const SkBitmap* sk_bitmap = lock.sk_bitmap();
2740 EXPECT_EQ(sk_bitmap->width(), size.width());
2741 EXPECT_EQ(sk_bitmap->height(), size.height());
2742 EXPECT_EQ(*sk_bitmap->getAddr32(16, 16), kBadBeef);
2745 resource_provider->DeleteResource(id);
2746 EXPECT_EQ(0u, release_sync_point);
2747 EXPECT_FALSE(lost_resource);
2748 EXPECT_EQ(main_thread_task_runner_.get(), main_thread_task_runner);
2751 class ResourceProviderTestTextureMailboxGLFilters
2752 : public ResourceProviderTest {
2753 public:
2754 static void RunTest(TestSharedBitmapManager* shared_bitmap_manager,
2755 TestGpuMemoryBufferManager* gpu_memory_buffer_manager,
2756 BlockingTaskRunner* main_thread_task_runner,
2757 bool mailbox_nearest_neighbor,
2758 GLenum sampler_filter) {
2759 scoped_ptr<TextureStateTrackingContext> context_owned(
2760 new TextureStateTrackingContext);
2761 TextureStateTrackingContext* context = context_owned.get();
2763 FakeOutputSurfaceClient output_surface_client;
2764 scoped_ptr<OutputSurface> output_surface(
2765 FakeOutputSurface::Create3d(context_owned.Pass()));
2766 CHECK(output_surface->BindToClient(&output_surface_client));
2768 scoped_ptr<ResourceProvider> resource_provider(
2769 ResourceProvider::Create(output_surface.get(),
2770 shared_bitmap_manager,
2771 gpu_memory_buffer_manager,
2772 main_thread_task_runner,
2774 false,
2775 1));
2777 unsigned texture_id = 1;
2778 uint32 sync_point = 30;
2779 unsigned target = GL_TEXTURE_2D;
2781 EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
2782 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
2783 EXPECT_CALL(*context, insertSyncPoint()).Times(0);
2784 EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _, _)).Times(0);
2785 EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(_, _)).Times(0);
2787 gpu::Mailbox gpu_mailbox;
2788 memcpy(gpu_mailbox.name, "Hello world", strlen("Hello world") + 1);
2789 uint32 release_sync_point = 0;
2790 bool lost_resource = false;
2791 BlockingTaskRunner* mailbox_task_runner = NULL;
2792 scoped_ptr<SingleReleaseCallbackImpl> callback =
2793 SingleReleaseCallbackImpl::Create(base::Bind(&ReleaseCallback,
2794 &release_sync_point,
2795 &lost_resource,
2796 &mailbox_task_runner));
2798 TextureMailbox mailbox(gpu_mailbox, target, sync_point);
2799 mailbox.set_nearest_neighbor(mailbox_nearest_neighbor);
2801 ResourceId id = resource_provider->CreateResourceFromTextureMailbox(
2802 mailbox, callback.Pass());
2803 EXPECT_NE(0u, id);
2805 Mock::VerifyAndClearExpectations(context);
2808 // Mailbox sync point WaitSyncPoint before using the texture.
2809 EXPECT_CALL(*context, waitSyncPoint(sync_point));
2810 resource_provider->WaitSyncPointIfNeeded(id);
2811 Mock::VerifyAndClearExpectations(context);
2813 EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(target, _))
2814 .WillOnce(Return(texture_id));
2815 EXPECT_CALL(*context, bindTexture(target, texture_id));
2817 EXPECT_CALL(*context, insertSyncPoint()).Times(0);
2818 EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _, _)).Times(0);
2820 // The sampler will reset these if |mailbox_nearest_neighbor| does not
2821 // match |sampler_filter|.
2822 if (mailbox_nearest_neighbor != (sampler_filter == GL_NEAREST)) {
2823 EXPECT_CALL(*context, texParameteri(
2824 GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, sampler_filter));
2825 EXPECT_CALL(*context, texParameteri(
2826 GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, sampler_filter));
2829 ResourceProvider::ScopedSamplerGL lock(
2830 resource_provider.get(), id, sampler_filter);
2831 Mock::VerifyAndClearExpectations(context);
2833 // When done with it, a sync point should be inserted, but no produce is
2834 // necessary.
2835 EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
2836 EXPECT_CALL(*context, insertSyncPoint());
2837 EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _, _)).Times(0);
2839 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
2840 EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(_, _)).Times(0);
2843 resource_provider->DeleteResource(id);
2844 EXPECT_EQ(0u, release_sync_point);
2845 EXPECT_FALSE(lost_resource);
2846 EXPECT_EQ(main_thread_task_runner, mailbox_task_runner);
2850 TEST_P(ResourceProviderTest, TextureMailbox_GLTexture2D_LinearToLinear) {
2851 // Mailboxing is only supported for GL textures.
2852 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
2853 return;
2855 ResourceProviderTestTextureMailboxGLFilters::RunTest(
2856 shared_bitmap_manager_.get(),
2857 gpu_memory_buffer_manager_.get(),
2858 main_thread_task_runner_.get(),
2859 false,
2860 GL_LINEAR);
2863 TEST_P(ResourceProviderTest, TextureMailbox_GLTexture2D_NearestToNearest) {
2864 // Mailboxing is only supported for GL textures.
2865 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
2866 return;
2868 ResourceProviderTestTextureMailboxGLFilters::RunTest(
2869 shared_bitmap_manager_.get(),
2870 gpu_memory_buffer_manager_.get(),
2871 main_thread_task_runner_.get(),
2872 true,
2873 GL_NEAREST);
2876 TEST_P(ResourceProviderTest, TextureMailbox_GLTexture2D_NearestToLinear) {
2877 // Mailboxing is only supported for GL textures.
2878 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
2879 return;
2881 ResourceProviderTestTextureMailboxGLFilters::RunTest(
2882 shared_bitmap_manager_.get(),
2883 gpu_memory_buffer_manager_.get(),
2884 main_thread_task_runner_.get(),
2885 true,
2886 GL_LINEAR);
2889 TEST_P(ResourceProviderTest, TextureMailbox_GLTexture2D_LinearToNearest) {
2890 // Mailboxing is only supported for GL textures.
2891 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
2892 return;
2894 ResourceProviderTestTextureMailboxGLFilters::RunTest(
2895 shared_bitmap_manager_.get(),
2896 gpu_memory_buffer_manager_.get(),
2897 main_thread_task_runner_.get(),
2898 false,
2899 GL_NEAREST);
2902 TEST_P(ResourceProviderTest, TextureMailbox_GLTextureExternalOES) {
2903 // Mailboxing is only supported for GL textures.
2904 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
2905 return;
2907 scoped_ptr<TextureStateTrackingContext> context_owned(
2908 new TextureStateTrackingContext);
2909 TextureStateTrackingContext* context = context_owned.get();
2911 FakeOutputSurfaceClient output_surface_client;
2912 scoped_ptr<OutputSurface> output_surface(
2913 FakeOutputSurface::Create3d(context_owned.Pass()));
2914 CHECK(output_surface->BindToClient(&output_surface_client));
2916 scoped_ptr<ResourceProvider> resource_provider(
2917 ResourceProvider::Create(output_surface.get(),
2918 shared_bitmap_manager_.get(),
2919 gpu_memory_buffer_manager_.get(),
2920 NULL,
2922 false,
2923 1));
2925 uint32 sync_point = 30;
2926 unsigned target = GL_TEXTURE_EXTERNAL_OES;
2928 EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
2929 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
2930 EXPECT_CALL(*context, insertSyncPoint()).Times(0);
2931 EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _, _)).Times(0);
2932 EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(_, _)).Times(0);
2934 gpu::Mailbox gpu_mailbox;
2935 memcpy(gpu_mailbox.name, "Hello world", strlen("Hello world") + 1);
2936 scoped_ptr<SingleReleaseCallbackImpl> callback =
2937 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback));
2939 TextureMailbox mailbox(gpu_mailbox, target, sync_point);
2941 ResourceId id = resource_provider->CreateResourceFromTextureMailbox(
2942 mailbox, callback.Pass());
2943 EXPECT_NE(0u, id);
2945 Mock::VerifyAndClearExpectations(context);
2948 // Mailbox sync point WaitSyncPoint before using the texture.
2949 EXPECT_CALL(*context, waitSyncPoint(sync_point));
2950 resource_provider->WaitSyncPointIfNeeded(id);
2951 Mock::VerifyAndClearExpectations(context);
2953 unsigned texture_id = 1;
2955 EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(target, _))
2956 .WillOnce(Return(texture_id));
2958 EXPECT_CALL(*context, insertSyncPoint()).Times(0);
2959 EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _, _)).Times(0);
2961 ResourceProvider::ScopedReadLockGL lock(resource_provider.get(), id);
2962 Mock::VerifyAndClearExpectations(context);
2964 // When done with it, a sync point should be inserted, but no produce is
2965 // necessary.
2966 EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
2967 EXPECT_CALL(*context, insertSyncPoint());
2968 EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _, _)).Times(0);
2970 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
2971 EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(_, _)).Times(0);
2975 TEST_P(ResourceProviderTest,
2976 TextureMailbox_WaitSyncPointIfNeeded_WithSyncPoint) {
2977 // Mailboxing is only supported for GL textures.
2978 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
2979 return;
2981 scoped_ptr<TextureStateTrackingContext> context_owned(
2982 new TextureStateTrackingContext);
2983 TextureStateTrackingContext* context = context_owned.get();
2985 FakeOutputSurfaceClient output_surface_client;
2986 scoped_ptr<OutputSurface> output_surface(
2987 FakeOutputSurface::Create3d(context_owned.Pass()));
2988 CHECK(output_surface->BindToClient(&output_surface_client));
2990 scoped_ptr<ResourceProvider> resource_provider(
2991 ResourceProvider::Create(output_surface.get(),
2992 shared_bitmap_manager_.get(),
2993 gpu_memory_buffer_manager_.get(),
2994 NULL,
2996 false,
2997 1));
2999 uint32 sync_point = 30;
3000 unsigned target = GL_TEXTURE_2D;
3002 EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
3003 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
3004 EXPECT_CALL(*context, insertSyncPoint()).Times(0);
3005 EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _, _)).Times(0);
3006 EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(_, _)).Times(0);
3008 gpu::Mailbox gpu_mailbox;
3009 memcpy(gpu_mailbox.name, "Hello world", strlen("Hello world") + 1);
3010 scoped_ptr<SingleReleaseCallbackImpl> callback =
3011 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback));
3013 TextureMailbox mailbox(gpu_mailbox, target, sync_point);
3015 ResourceId id = resource_provider->CreateResourceFromTextureMailbox(
3016 mailbox, callback.Pass());
3017 EXPECT_NE(0u, id);
3019 Mock::VerifyAndClearExpectations(context);
3022 // First call to WaitSyncPointIfNeeded should call waitSyncPoint.
3023 EXPECT_CALL(*context, waitSyncPoint(sync_point));
3024 resource_provider->WaitSyncPointIfNeeded(id);
3025 Mock::VerifyAndClearExpectations(context);
3027 // Subsequent calls to WaitSyncPointIfNeeded shouldn't call waitSyncPoint.
3028 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
3029 resource_provider->WaitSyncPointIfNeeded(id);
3030 Mock::VerifyAndClearExpectations(context);
3034 TEST_P(ResourceProviderTest, TextureMailbox_WaitSyncPointIfNeeded_NoSyncPoint) {
3035 // Mailboxing is only supported for GL textures.
3036 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
3037 return;
3039 scoped_ptr<TextureStateTrackingContext> context_owned(
3040 new TextureStateTrackingContext);
3041 TextureStateTrackingContext* context = context_owned.get();
3043 FakeOutputSurfaceClient output_surface_client;
3044 scoped_ptr<OutputSurface> output_surface(
3045 FakeOutputSurface::Create3d(context_owned.Pass()));
3046 CHECK(output_surface->BindToClient(&output_surface_client));
3048 scoped_ptr<ResourceProvider> resource_provider(
3049 ResourceProvider::Create(output_surface.get(),
3050 shared_bitmap_manager_.get(),
3051 gpu_memory_buffer_manager_.get(),
3052 NULL,
3054 false,
3055 1));
3057 uint32 sync_point = 0;
3058 unsigned target = GL_TEXTURE_2D;
3060 EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
3061 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
3062 EXPECT_CALL(*context, insertSyncPoint()).Times(0);
3063 EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _, _)).Times(0);
3064 EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(_, _)).Times(0);
3066 gpu::Mailbox gpu_mailbox;
3067 memcpy(gpu_mailbox.name, "Hello world", strlen("Hello world") + 1);
3068 scoped_ptr<SingleReleaseCallbackImpl> callback =
3069 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback));
3071 TextureMailbox mailbox(gpu_mailbox, target, sync_point);
3073 ResourceId id = resource_provider->CreateResourceFromTextureMailbox(
3074 mailbox, callback.Pass());
3075 EXPECT_NE(0u, id);
3077 Mock::VerifyAndClearExpectations(context);
3080 // WaitSyncPointIfNeeded with sync_point == 0 shouldn't call waitSyncPoint.
3081 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
3082 resource_provider->WaitSyncPointIfNeeded(id);
3083 Mock::VerifyAndClearExpectations(context);
3087 class AllocationTrackingContext3D : public TestWebGraphicsContext3D {
3088 public:
3089 MOCK_METHOD0(NextTextureId, GLuint());
3090 MOCK_METHOD1(RetireTextureId, void(GLuint id));
3091 MOCK_METHOD2(bindTexture, void(GLenum target, GLuint texture));
3092 MOCK_METHOD5(texStorage2DEXT,
3093 void(GLenum target,
3094 GLint levels,
3095 GLuint internalformat,
3096 GLint width,
3097 GLint height));
3098 MOCK_METHOD9(texImage2D,
3099 void(GLenum target,
3100 GLint level,
3101 GLenum internalformat,
3102 GLsizei width,
3103 GLsizei height,
3104 GLint border,
3105 GLenum format,
3106 GLenum type,
3107 const void* pixels));
3108 MOCK_METHOD9(texSubImage2D,
3109 void(GLenum target,
3110 GLint level,
3111 GLint xoffset,
3112 GLint yoffset,
3113 GLsizei width,
3114 GLsizei height,
3115 GLenum format,
3116 GLenum type,
3117 const void* pixels));
3118 MOCK_METHOD9(asyncTexImage2DCHROMIUM,
3119 void(GLenum target,
3120 GLint level,
3121 GLenum internalformat,
3122 GLsizei width,
3123 GLsizei height,
3124 GLint border,
3125 GLenum format,
3126 GLenum type,
3127 const void* pixels));
3128 MOCK_METHOD9(asyncTexSubImage2DCHROMIUM,
3129 void(GLenum target,
3130 GLint level,
3131 GLint xoffset,
3132 GLint yoffset,
3133 GLsizei width,
3134 GLsizei height,
3135 GLenum format,
3136 GLenum type,
3137 const void* pixels));
3138 MOCK_METHOD8(compressedTexImage2D,
3139 void(GLenum target,
3140 GLint level,
3141 GLenum internalformat,
3142 GLsizei width,
3143 GLsizei height,
3144 GLint border,
3145 GLsizei image_size,
3146 const void* data));
3147 MOCK_METHOD1(waitAsyncTexImage2DCHROMIUM, void(GLenum));
3148 MOCK_METHOD4(createImageCHROMIUM,
3149 GLuint(ClientBuffer, GLsizei, GLsizei, GLenum));
3150 MOCK_METHOD1(destroyImageCHROMIUM, void(GLuint));
3151 MOCK_METHOD2(bindTexImage2DCHROMIUM, void(GLenum, GLint));
3152 MOCK_METHOD2(releaseTexImage2DCHROMIUM, void(GLenum, GLint));
3154 // We're mocking bindTexture, so we override
3155 // TestWebGraphicsContext3D::texParameteri to avoid assertions related to the
3156 // currently bound texture.
3157 virtual void texParameteri(GLenum target, GLenum pname, GLint param) {}
3160 TEST_P(ResourceProviderTest, TextureAllocation) {
3161 // Only for GL textures.
3162 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
3163 return;
3164 scoped_ptr<AllocationTrackingContext3D> context_owned(
3165 new StrictMock<AllocationTrackingContext3D>);
3166 AllocationTrackingContext3D* context = context_owned.get();
3168 FakeOutputSurfaceClient output_surface_client;
3169 scoped_ptr<OutputSurface> output_surface(
3170 FakeOutputSurface::Create3d(context_owned.Pass()));
3171 CHECK(output_surface->BindToClient(&output_surface_client));
3173 scoped_ptr<ResourceProvider> resource_provider(
3174 ResourceProvider::Create(output_surface.get(),
3175 shared_bitmap_manager_.get(),
3176 gpu_memory_buffer_manager_.get(),
3177 NULL,
3179 false,
3180 1));
3182 gfx::Size size(2, 2);
3183 gfx::Vector2d offset(0, 0);
3184 ResourceFormat format = RGBA_8888;
3185 ResourceId id = 0;
3186 uint8_t pixels[16] = { 0 };
3187 int texture_id = 123;
3189 // Lazy allocation. Don't allocate when creating the resource.
3190 id = resource_provider->CreateResource(
3191 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
3193 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3194 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(1);
3195 resource_provider->CreateForTesting(id);
3197 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3198 resource_provider->DeleteResource(id);
3200 Mock::VerifyAndClearExpectations(context);
3202 // Do allocate when we set the pixels.
3203 id = resource_provider->CreateResource(
3204 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
3206 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3207 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(3);
3208 EXPECT_CALL(*context, texImage2D(_, _, _, 2, 2, _, _, _, _)).Times(1);
3209 EXPECT_CALL(*context, texSubImage2D(_, _, _, _, 2, 2, _, _, _)).Times(1);
3210 resource_provider->CopyToResource(id, pixels, size);
3212 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3213 resource_provider->DeleteResource(id);
3215 Mock::VerifyAndClearExpectations(context);
3217 // Same for async version.
3218 id = resource_provider->CreateResource(
3219 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
3220 resource_provider->AcquirePixelBuffer(id);
3222 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3223 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
3224 EXPECT_CALL(*context, asyncTexImage2DCHROMIUM(_, _, _, 2, 2, _, _, _, _))
3225 .Times(1);
3226 resource_provider->BeginSetPixels(id);
3227 ASSERT_TRUE(resource_provider->DidSetPixelsComplete(id));
3229 resource_provider->ReleasePixelBuffer(id);
3231 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3232 resource_provider->DeleteResource(id);
3234 Mock::VerifyAndClearExpectations(context);
3237 TEST_P(ResourceProviderTest, TextureAllocationHint) {
3238 // Only for GL textures.
3239 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
3240 return;
3241 scoped_ptr<AllocationTrackingContext3D> context_owned(
3242 new StrictMock<AllocationTrackingContext3D>);
3243 AllocationTrackingContext3D* context = context_owned.get();
3244 context->set_support_texture_storage(true);
3245 context->set_support_texture_usage(true);
3247 FakeOutputSurfaceClient output_surface_client;
3248 scoped_ptr<OutputSurface> output_surface(
3249 FakeOutputSurface::Create3d(context_owned.Pass()));
3250 CHECK(output_surface->BindToClient(&output_surface_client));
3252 scoped_ptr<ResourceProvider> resource_provider(
3253 ResourceProvider::Create(output_surface.get(),
3254 shared_bitmap_manager_.get(),
3255 gpu_memory_buffer_manager_.get(),
3256 NULL,
3258 false,
3259 1));
3261 gfx::Size size(2, 2);
3263 const ResourceFormat formats[2] = {RGBA_8888, BGRA_8888};
3264 const ResourceProvider::TextureHint hints[4] = {
3265 ResourceProvider::TEXTURE_HINT_DEFAULT,
3266 ResourceProvider::TEXTURE_HINT_IMMUTABLE,
3267 ResourceProvider::TEXTURE_HINT_FRAMEBUFFER,
3268 ResourceProvider::TEXTURE_HINT_IMMUTABLE_FRAMEBUFFER,
3270 for (size_t i = 0; i < arraysize(formats); ++i) {
3271 for (GLuint texture_id = 1; texture_id <= arraysize(hints); ++texture_id) {
3272 // Lazy allocation. Don't allocate when creating the resource.
3273 ResourceId id = resource_provider->CreateResource(
3274 size, GL_CLAMP_TO_EDGE, hints[texture_id - 1], formats[i]);
3276 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3277 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
3278 bool is_immutable_hint =
3279 hints[texture_id - 1] & ResourceProvider::TEXTURE_HINT_IMMUTABLE;
3280 bool support_immutable_texture =
3281 is_immutable_hint && formats[i] == RGBA_8888;
3282 EXPECT_CALL(*context, texStorage2DEXT(_, _, _, 2, 2))
3283 .Times(support_immutable_texture ? 1 : 0);
3284 EXPECT_CALL(*context, texImage2D(_, _, _, 2, 2, _, _, _, _))
3285 .Times(support_immutable_texture ? 0 : 1);
3286 resource_provider->AllocateForTesting(id);
3288 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3289 resource_provider->DeleteResource(id);
3291 Mock::VerifyAndClearExpectations(context);
3296 TEST_P(ResourceProviderTest, TextureAllocationHint_BGRA) {
3297 // Only for GL textures.
3298 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
3299 return;
3300 scoped_ptr<AllocationTrackingContext3D> context_owned(
3301 new StrictMock<AllocationTrackingContext3D>);
3302 AllocationTrackingContext3D* context = context_owned.get();
3303 context->set_support_texture_format_bgra8888(true);
3304 context->set_support_texture_storage(true);
3305 context->set_support_texture_usage(true);
3307 FakeOutputSurfaceClient output_surface_client;
3308 scoped_ptr<OutputSurface> output_surface(
3309 FakeOutputSurface::Create3d(context_owned.Pass()));
3310 CHECK(output_surface->BindToClient(&output_surface_client));
3312 scoped_ptr<ResourceProvider> resource_provider(
3313 ResourceProvider::Create(output_surface.get(),
3314 shared_bitmap_manager_.get(),
3315 gpu_memory_buffer_manager_.get(),
3316 NULL,
3318 false,
3319 1));
3321 gfx::Size size(2, 2);
3322 const ResourceFormat formats[2] = {RGBA_8888, BGRA_8888};
3324 const ResourceProvider::TextureHint hints[4] = {
3325 ResourceProvider::TEXTURE_HINT_DEFAULT,
3326 ResourceProvider::TEXTURE_HINT_IMMUTABLE,
3327 ResourceProvider::TEXTURE_HINT_FRAMEBUFFER,
3328 ResourceProvider::TEXTURE_HINT_IMMUTABLE_FRAMEBUFFER,
3330 for (size_t i = 0; i < arraysize(formats); ++i) {
3331 for (GLuint texture_id = 1; texture_id <= arraysize(hints); ++texture_id) {
3332 // Lazy allocation. Don't allocate when creating the resource.
3333 ResourceId id = resource_provider->CreateResource(
3334 size, GL_CLAMP_TO_EDGE, hints[texture_id - 1], formats[i]);
3336 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3337 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
3338 bool is_immutable_hint =
3339 hints[texture_id - 1] & ResourceProvider::TEXTURE_HINT_IMMUTABLE;
3340 EXPECT_CALL(*context, texStorage2DEXT(_, _, _, 2, 2))
3341 .Times(is_immutable_hint ? 1 : 0);
3342 EXPECT_CALL(*context, texImage2D(_, _, _, 2, 2, _, _, _, _))
3343 .Times(is_immutable_hint ? 0 : 1);
3344 resource_provider->AllocateForTesting(id);
3346 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3347 resource_provider->DeleteResource(id);
3349 Mock::VerifyAndClearExpectations(context);
3354 TEST_P(ResourceProviderTest, PixelBuffer_GLTexture) {
3355 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
3356 return;
3357 scoped_ptr<AllocationTrackingContext3D> context_owned(
3358 new StrictMock<AllocationTrackingContext3D>);
3359 AllocationTrackingContext3D* context = context_owned.get();
3361 FakeOutputSurfaceClient output_surface_client;
3362 scoped_ptr<OutputSurface> output_surface(
3363 FakeOutputSurface::Create3d(context_owned.Pass()));
3364 CHECK(output_surface->BindToClient(&output_surface_client));
3366 gfx::Size size(2, 2);
3367 ResourceFormat format = RGBA_8888;
3368 ResourceId id = 0;
3369 int texture_id = 123;
3371 scoped_ptr<ResourceProvider> resource_provider(
3372 ResourceProvider::Create(output_surface.get(),
3373 shared_bitmap_manager_.get(),
3374 gpu_memory_buffer_manager_.get(),
3375 NULL,
3377 false,
3378 1));
3380 id = resource_provider->CreateResource(
3381 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
3382 resource_provider->AcquirePixelBuffer(id);
3384 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3385 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
3386 EXPECT_CALL(*context, asyncTexImage2DCHROMIUM(_, _, _, 2, 2, _, _, _, _))
3387 .Times(1);
3388 resource_provider->BeginSetPixels(id);
3390 EXPECT_TRUE(resource_provider->DidSetPixelsComplete(id));
3392 resource_provider->ReleasePixelBuffer(id);
3394 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3395 resource_provider->DeleteResource(id);
3397 Mock::VerifyAndClearExpectations(context);
3400 TEST_P(ResourceProviderTest, ForcingAsyncUploadToComplete) {
3401 // Only for GL textures.
3402 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
3403 return;
3404 scoped_ptr<AllocationTrackingContext3D> context_owned(
3405 new StrictMock<AllocationTrackingContext3D>);
3406 AllocationTrackingContext3D* context = context_owned.get();
3408 FakeOutputSurfaceClient output_surface_client;
3409 scoped_ptr<OutputSurface> output_surface(
3410 FakeOutputSurface::Create3d(context_owned.Pass()));
3411 CHECK(output_surface->BindToClient(&output_surface_client));
3413 gfx::Size size(2, 2);
3414 ResourceFormat format = RGBA_8888;
3415 ResourceId id = 0;
3416 int texture_id = 123;
3418 scoped_ptr<ResourceProvider> resource_provider(
3419 ResourceProvider::Create(output_surface.get(),
3420 shared_bitmap_manager_.get(),
3421 gpu_memory_buffer_manager_.get(),
3422 NULL,
3424 false,
3425 1));
3427 id = resource_provider->CreateResource(
3428 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
3429 resource_provider->AcquirePixelBuffer(id);
3431 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3432 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
3433 EXPECT_CALL(*context, asyncTexImage2DCHROMIUM(_, _, _, 2, 2, _, _, _, _))
3434 .Times(1);
3435 resource_provider->BeginSetPixels(id);
3437 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(1);
3438 EXPECT_CALL(*context, waitAsyncTexImage2DCHROMIUM(GL_TEXTURE_2D)).Times(1);
3439 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, 0)).Times(1);
3440 resource_provider->ForceSetPixelsToComplete(id);
3442 resource_provider->ReleasePixelBuffer(id);
3444 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3445 resource_provider->DeleteResource(id);
3447 Mock::VerifyAndClearExpectations(context);
3450 TEST_P(ResourceProviderTest, PixelBufferLostContext) {
3451 scoped_ptr<AllocationTrackingContext3D> context_owned(
3452 new NiceMock<AllocationTrackingContext3D>);
3453 AllocationTrackingContext3D* context = context_owned.get();
3455 FakeOutputSurfaceClient output_surface_client;
3456 scoped_ptr<OutputSurface> output_surface(
3457 FakeOutputSurface::Create3d(context_owned.Pass()));
3458 CHECK(output_surface->BindToClient(&output_surface_client));
3460 gfx::Size size(2, 2);
3461 ResourceFormat format = RGBA_8888;
3462 ResourceId id = 0;
3463 int texture_id = 123;
3465 scoped_ptr<ResourceProvider> resource_provider(
3466 ResourceProvider::Create(output_surface.get(),
3467 shared_bitmap_manager_.get(),
3468 gpu_memory_buffer_manager_.get(),
3469 NULL,
3471 false,
3472 1));
3474 EXPECT_CALL(*context, NextTextureId()).WillRepeatedly(Return(texture_id));
3476 id = resource_provider->CreateResource(
3477 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
3478 context->loseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB,
3479 GL_INNOCENT_CONTEXT_RESET_ARB);
3481 resource_provider->AcquirePixelBuffer(id);
3482 int stride;
3483 void* buffer = resource_provider->MapPixelBuffer(id, &stride);
3484 EXPECT_FALSE(buffer);
3485 resource_provider->UnmapPixelBuffer(id);
3486 Mock::VerifyAndClearExpectations(context);
3489 TEST_P(ResourceProviderTest, Image_GLTexture) {
3490 // Only for GL textures.
3491 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
3492 return;
3493 scoped_ptr<AllocationTrackingContext3D> context_owned(
3494 new StrictMock<AllocationTrackingContext3D>);
3495 AllocationTrackingContext3D* context = context_owned.get();
3497 FakeOutputSurfaceClient output_surface_client;
3498 scoped_ptr<OutputSurface> output_surface(
3499 FakeOutputSurface::Create3d(context_owned.Pass()));
3500 CHECK(output_surface->BindToClient(&output_surface_client));
3502 const int kWidth = 2;
3503 const int kHeight = 2;
3504 gfx::Size size(kWidth, kHeight);
3505 ResourceFormat format = RGBA_8888;
3506 ResourceId id = 0;
3507 const unsigned kTextureId = 123u;
3508 const unsigned kImageId = 234u;
3510 scoped_ptr<ResourceProvider> resource_provider(
3511 ResourceProvider::Create(output_surface.get(),
3512 shared_bitmap_manager_.get(),
3513 gpu_memory_buffer_manager_.get(),
3514 NULL,
3516 false,
3517 1));
3519 id = resource_provider->CreateResource(
3520 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
3522 EXPECT_CALL(*context, createImageCHROMIUM(_, kWidth, kHeight, GL_RGBA))
3523 .WillOnce(Return(kImageId))
3524 .RetiresOnSaturation();
3526 ResourceProvider::ScopedWriteLockGpuMemoryBuffer lock(
3527 resource_provider.get(), id);
3528 EXPECT_TRUE(lock.GetGpuMemoryBuffer());
3531 EXPECT_CALL(*context, NextTextureId())
3532 .WillOnce(Return(kTextureId))
3533 .RetiresOnSaturation();
3534 // Once in CreateTextureId and once in BindForSampling
3535 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kTextureId)).Times(2)
3536 .RetiresOnSaturation();
3537 EXPECT_CALL(*context, bindTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId))
3538 .Times(1)
3539 .RetiresOnSaturation();
3541 ResourceProvider::ScopedSamplerGL lock_gl(
3542 resource_provider.get(), id, GL_TEXTURE_2D, GL_LINEAR);
3543 EXPECT_EQ(kTextureId, lock_gl.texture_id());
3547 ResourceProvider::ScopedWriteLockGpuMemoryBuffer lock(
3548 resource_provider.get(), id);
3549 EXPECT_TRUE(lock.GetGpuMemoryBuffer());
3552 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kTextureId)).Times(1)
3553 .RetiresOnSaturation();
3554 EXPECT_CALL(*context, releaseTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId))
3555 .Times(1)
3556 .RetiresOnSaturation();
3557 EXPECT_CALL(*context, bindTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId))
3558 .Times(1)
3559 .RetiresOnSaturation();
3560 EXPECT_CALL(*context, RetireTextureId(kTextureId))
3561 .Times(1)
3562 .RetiresOnSaturation();
3564 ResourceProvider::ScopedSamplerGL lock_gl(
3565 resource_provider.get(), id, GL_TEXTURE_2D, GL_LINEAR);
3566 EXPECT_EQ(kTextureId, lock_gl.texture_id());
3569 EXPECT_CALL(*context, destroyImageCHROMIUM(kImageId))
3570 .Times(1)
3571 .RetiresOnSaturation();
3574 TEST_P(ResourceProviderTest, CopyResource_GLTexture) {
3575 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
3576 return;
3577 scoped_ptr<AllocationTrackingContext3D> context_owned(
3578 new StrictMock<AllocationTrackingContext3D>);
3579 AllocationTrackingContext3D* context = context_owned.get();
3580 context_owned->set_support_sync_query(true);
3582 FakeOutputSurfaceClient output_surface_client;
3583 scoped_ptr<OutputSurface> output_surface(
3584 FakeOutputSurface::Create3d(context_owned.Pass()));
3585 ASSERT_TRUE(output_surface->BindToClient(&output_surface_client));
3587 const int kWidth = 2;
3588 const int kHeight = 2;
3589 gfx::Size size(kWidth, kHeight);
3590 ResourceFormat format = RGBA_8888;
3591 ResourceId source_id = 0;
3592 ResourceId dest_id = 0;
3593 const unsigned kSourceTextureId = 123u;
3594 const unsigned kDestTextureId = 321u;
3595 const unsigned kImageId = 234u;
3597 scoped_ptr<ResourceProvider> resource_provider(
3598 ResourceProvider::Create(output_surface.get(),
3599 shared_bitmap_manager_.get(),
3600 gpu_memory_buffer_manager_.get(),
3601 NULL,
3603 false,
3604 1));
3606 source_id = resource_provider->CreateResource(
3607 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
3609 EXPECT_CALL(*context, createImageCHROMIUM(_, kWidth, kHeight, GL_RGBA))
3610 .WillOnce(Return(kImageId))
3611 .RetiresOnSaturation();
3613 ResourceProvider::ScopedWriteLockGpuMemoryBuffer lock(
3614 resource_provider.get(), source_id);
3615 EXPECT_TRUE(lock.GetGpuMemoryBuffer());
3617 Mock::VerifyAndClearExpectations(context);
3619 dest_id = resource_provider->CreateResource(
3620 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
3622 EXPECT_CALL(*context, NextTextureId())
3623 .WillOnce(Return(kDestTextureId))
3624 .RetiresOnSaturation();
3625 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kDestTextureId))
3626 .Times(2)
3627 .RetiresOnSaturation();
3628 EXPECT_CALL(*context, texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA,
3629 GL_UNSIGNED_BYTE, nullptr))
3630 .Times(1)
3631 .RetiresOnSaturation();
3632 EXPECT_CALL(*context, NextTextureId())
3633 .WillOnce(Return(kSourceTextureId))
3634 .RetiresOnSaturation();
3635 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kSourceTextureId))
3636 .Times(2)
3637 .RetiresOnSaturation();
3638 EXPECT_CALL(*context, bindTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId))
3639 .Times(1)
3640 .RetiresOnSaturation();
3641 resource_provider->CopyResource(source_id, dest_id, gfx::Rect(size));
3642 Mock::VerifyAndClearExpectations(context);
3644 EXPECT_CALL(*context, destroyImageCHROMIUM(kImageId))
3645 .Times(1)
3646 .RetiresOnSaturation();
3647 EXPECT_CALL(*context, RetireTextureId(kSourceTextureId))
3648 .Times(1)
3649 .RetiresOnSaturation();
3650 EXPECT_CALL(*context, RetireTextureId(kDestTextureId))
3651 .Times(1)
3652 .RetiresOnSaturation();
3653 resource_provider->DeleteResource(source_id);
3654 resource_provider->DeleteResource(dest_id);
3657 TEST_P(ResourceProviderTest, CompressedTextureETC1Allocate) {
3658 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
3659 return;
3661 scoped_ptr<AllocationTrackingContext3D> context_owned(
3662 new AllocationTrackingContext3D);
3663 AllocationTrackingContext3D* context = context_owned.get();
3664 context_owned->set_support_compressed_texture_etc1(true);
3666 FakeOutputSurfaceClient output_surface_client;
3667 scoped_ptr<OutputSurface> output_surface(
3668 FakeOutputSurface::Create3d(context_owned.Pass()));
3669 CHECK(output_surface->BindToClient(&output_surface_client));
3671 gfx::Size size(4, 4);
3672 scoped_ptr<ResourceProvider> resource_provider(
3673 ResourceProvider::Create(output_surface.get(),
3674 shared_bitmap_manager_.get(),
3675 gpu_memory_buffer_manager_.get(),
3676 NULL,
3678 false,
3679 1));
3680 int texture_id = 123;
3682 ResourceId id = resource_provider->CreateResource(
3683 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, ETC1);
3684 EXPECT_NE(0u, id);
3685 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3686 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
3687 resource_provider->AllocateForTesting(id);
3689 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3690 resource_provider->DeleteResource(id);
3693 TEST_P(ResourceProviderTest, CompressedTextureETC1Upload) {
3694 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
3695 return;
3697 scoped_ptr<AllocationTrackingContext3D> context_owned(
3698 new AllocationTrackingContext3D);
3699 AllocationTrackingContext3D* context = context_owned.get();
3700 context_owned->set_support_compressed_texture_etc1(true);
3702 FakeOutputSurfaceClient output_surface_client;
3703 scoped_ptr<OutputSurface> output_surface(
3704 FakeOutputSurface::Create3d(context_owned.Pass()));
3705 CHECK(output_surface->BindToClient(&output_surface_client));
3707 gfx::Size size(4, 4);
3708 scoped_ptr<ResourceProvider> resource_provider(
3709 ResourceProvider::Create(output_surface.get(),
3710 shared_bitmap_manager_.get(),
3711 gpu_memory_buffer_manager_.get(),
3712 NULL,
3714 false,
3715 1));
3716 int texture_id = 123;
3717 uint8_t pixels[8];
3719 ResourceId id = resource_provider->CreateResource(
3720 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, ETC1);
3721 EXPECT_NE(0u, id);
3722 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3723 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(3);
3724 EXPECT_CALL(*context,
3725 compressedTexImage2D(
3726 _, 0, _, size.width(), size.height(), _, _, _)).Times(1);
3727 resource_provider->CopyToResource(id, pixels, size);
3729 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3730 resource_provider->DeleteResource(id);
3733 INSTANTIATE_TEST_CASE_P(
3734 ResourceProviderTests,
3735 ResourceProviderTest,
3736 ::testing::Values(ResourceProvider::RESOURCE_TYPE_GL_TEXTURE,
3737 ResourceProvider::RESOURCE_TYPE_BITMAP));
3739 class TextureIdAllocationTrackingContext : public TestWebGraphicsContext3D {
3740 public:
3741 GLuint NextTextureId() override {
3742 base::AutoLock lock(namespace_->lock);
3743 return namespace_->next_texture_id++;
3745 void RetireTextureId(GLuint) override {}
3746 GLuint PeekTextureId() {
3747 base::AutoLock lock(namespace_->lock);
3748 return namespace_->next_texture_id;
3752 TEST(ResourceProviderTest, TextureAllocationChunkSize) {
3753 scoped_ptr<TextureIdAllocationTrackingContext> context_owned(
3754 new TextureIdAllocationTrackingContext);
3755 TextureIdAllocationTrackingContext* context = context_owned.get();
3757 FakeOutputSurfaceClient output_surface_client;
3758 scoped_ptr<OutputSurface> output_surface(
3759 FakeOutputSurface::Create3d(context_owned.Pass()));
3760 CHECK(output_surface->BindToClient(&output_surface_client));
3761 scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
3762 new TestSharedBitmapManager());
3764 gfx::Size size(1, 1);
3765 ResourceFormat format = RGBA_8888;
3768 size_t kTextureAllocationChunkSize = 1;
3769 scoped_ptr<ResourceProvider> resource_provider(
3770 ResourceProvider::Create(output_surface.get(),
3771 shared_bitmap_manager.get(),
3772 NULL,
3773 NULL,
3775 false,
3776 kTextureAllocationChunkSize));
3778 ResourceId id = resource_provider->CreateResource(
3779 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE,
3780 format);
3781 resource_provider->AllocateForTesting(id);
3782 Mock::VerifyAndClearExpectations(context);
3784 DCHECK_EQ(2u, context->PeekTextureId());
3785 resource_provider->DeleteResource(id);
3789 size_t kTextureAllocationChunkSize = 8;
3790 scoped_ptr<ResourceProvider> resource_provider(
3791 ResourceProvider::Create(output_surface.get(),
3792 shared_bitmap_manager.get(),
3793 NULL,
3794 NULL,
3796 false,
3797 kTextureAllocationChunkSize));
3799 ResourceId id = resource_provider->CreateResource(
3800 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE,
3801 format);
3802 resource_provider->AllocateForTesting(id);
3803 Mock::VerifyAndClearExpectations(context);
3805 DCHECK_EQ(10u, context->PeekTextureId());
3806 resource_provider->DeleteResource(id);
3810 } // namespace
3811 } // namespace cc