Setup a experiment to enable background tracing.
[chromium-blink-merge.git] / cc / resources / resource_provider_unittest.cc
blob7ad0e8678f58ecd019bb9dfc211d663fcfbe1ce4
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_ = ResourceProvider::Create(
422 output_surface_.get(), shared_bitmap_manager_.get(),
423 gpu_memory_buffer_manager_.get(), main_thread_task_runner_.get(), 0,
424 false, 1, false);
425 child_resource_provider_ = ResourceProvider::Create(
426 child_output_surface_.get(), shared_bitmap_manager_.get(),
427 gpu_memory_buffer_manager_.get(), main_thread_task_runner_.get(), 0,
428 false, 1, false);
431 ResourceProviderTest() : ResourceProviderTest(true) {}
433 static void CollectResources(ReturnedResourceArray* array,
434 const ReturnedResourceArray& returned,
435 BlockingTaskRunner* main_thread_task_runner) {
436 array->insert(array->end(), returned.begin(), returned.end());
439 static ReturnCallback GetReturnCallback(ReturnedResourceArray* array) {
440 return base::Bind(&ResourceProviderTest::CollectResources, array);
443 static void SetResourceFilter(ResourceProvider* resource_provider,
444 ResourceId id,
445 GLenum filter) {
446 ResourceProvider::ScopedSamplerGL sampler(
447 resource_provider, id, GL_TEXTURE_2D, filter);
450 ResourceProviderContext* context() { return context3d_; }
452 ResourceId CreateChildMailbox(uint32* release_sync_point,
453 bool* lost_resource,
454 bool* release_called,
455 uint32* sync_point) {
456 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) {
457 unsigned texture = child_context_->createTexture();
458 gpu::Mailbox gpu_mailbox;
459 child_context_->genMailboxCHROMIUM(gpu_mailbox.name);
460 child_context_->produceTextureDirectCHROMIUM(texture, GL_TEXTURE_2D,
461 gpu_mailbox.name);
462 *sync_point = child_context_->insertSyncPoint();
463 EXPECT_LT(0u, *sync_point);
465 scoped_ptr<SharedBitmap> shared_bitmap;
466 scoped_ptr<SingleReleaseCallbackImpl> callback =
467 SingleReleaseCallbackImpl::Create(base::Bind(
468 ReleaseSharedBitmapCallback, base::Passed(&shared_bitmap),
469 release_called, release_sync_point, lost_resource));
470 return child_resource_provider_->CreateResourceFromTextureMailbox(
471 TextureMailbox(gpu_mailbox, GL_TEXTURE_2D, *sync_point),
472 callback.Pass());
473 } else {
474 gfx::Size size(64, 64);
475 scoped_ptr<SharedBitmap> shared_bitmap(
476 CreateAndFillSharedBitmap(shared_bitmap_manager_.get(), size, 0));
478 SharedBitmap* shared_bitmap_ptr = shared_bitmap.get();
479 scoped_ptr<SingleReleaseCallbackImpl> callback =
480 SingleReleaseCallbackImpl::Create(base::Bind(
481 ReleaseSharedBitmapCallback, base::Passed(&shared_bitmap),
482 release_called, release_sync_point, lost_resource));
483 return child_resource_provider_->CreateResourceFromTextureMailbox(
484 TextureMailbox(shared_bitmap_ptr, size), callback.Pass());
488 protected:
489 scoped_ptr<ContextSharedData> shared_data_;
490 ResourceProviderContext* context3d_;
491 ResourceProviderContext* child_context_;
492 FakeOutputSurfaceClient output_surface_client_;
493 FakeOutputSurfaceClient child_output_surface_client_;
494 scoped_ptr<OutputSurface> output_surface_;
495 scoped_ptr<OutputSurface> child_output_surface_;
496 scoped_ptr<BlockingTaskRunner> main_thread_task_runner_;
497 scoped_ptr<ResourceProvider> resource_provider_;
498 scoped_ptr<ResourceProvider> child_resource_provider_;
499 scoped_ptr<TestSharedBitmapManager> shared_bitmap_manager_;
500 scoped_ptr<TestGpuMemoryBufferManager> gpu_memory_buffer_manager_;
503 void CheckCreateResource(ResourceProvider::ResourceType expected_default_type,
504 ResourceProvider* resource_provider,
505 ResourceProviderContext* context) {
506 DCHECK_EQ(expected_default_type, resource_provider->default_resource_type());
508 gfx::Size size(1, 1);
509 ResourceFormat format = RGBA_8888;
510 size_t pixel_size = TextureSizeBytes(size, format);
511 ASSERT_EQ(4U, pixel_size);
513 ResourceId id = resource_provider->CreateResource(
514 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
515 EXPECT_EQ(1, static_cast<int>(resource_provider->num_resources()));
516 if (expected_default_type == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
517 EXPECT_EQ(0u, context->NumTextures());
519 uint8_t data[4] = { 1, 2, 3, 4 };
520 resource_provider->CopyToResource(id, data, size);
521 if (expected_default_type == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
522 EXPECT_EQ(1u, context->NumTextures());
524 uint8_t result[4] = { 0 };
525 GetResourcePixels(resource_provider, context, id, size, format, result);
526 EXPECT_EQ(0, memcmp(data, result, pixel_size));
528 resource_provider->DeleteResource(id);
529 EXPECT_EQ(0, static_cast<int>(resource_provider->num_resources()));
530 if (expected_default_type == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
531 EXPECT_EQ(0u, context->NumTextures());
534 TEST_P(ResourceProviderTest, Basic) {
535 CheckCreateResource(GetParam(), resource_provider_.get(), context());
538 TEST_P(ResourceProviderTest, Upload) {
539 gfx::Size size(2, 2);
540 ResourceFormat format = RGBA_8888;
541 size_t pixel_size = TextureSizeBytes(size, format);
542 ASSERT_EQ(16U, pixel_size);
544 ResourceId id = resource_provider_->CreateResource(
545 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
547 uint8_t image[16] = { 0 };
548 gfx::Rect image_rect(size);
549 resource_provider_->SetPixels(
550 id, image, image_rect, image_rect, gfx::Vector2d());
552 for (uint8_t i = 0; i < pixel_size; ++i)
553 image[i] = i;
555 uint8_t result[16] = { 0 };
557 gfx::Rect source_rect(0, 0, 1, 1);
558 gfx::Vector2d dest_offset(0, 0);
559 resource_provider_->SetPixels(
560 id, image, image_rect, source_rect, dest_offset);
562 uint8_t expected[16] = { 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
563 GetResourcePixels(
564 resource_provider_.get(), context(), id, size, format, result);
565 EXPECT_EQ(0, memcmp(expected, result, pixel_size));
568 gfx::Rect source_rect(0, 0, 1, 1);
569 gfx::Vector2d dest_offset(1, 1);
570 resource_provider_->SetPixels(
571 id, image, image_rect, source_rect, dest_offset);
573 uint8_t expected[16] = { 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3 };
574 GetResourcePixels(
575 resource_provider_.get(), context(), id, size, format, result);
576 EXPECT_EQ(0, memcmp(expected, result, pixel_size));
579 gfx::Rect source_rect(1, 0, 1, 1);
580 gfx::Vector2d dest_offset(0, 1);
581 resource_provider_->SetPixels(
582 id, image, image_rect, source_rect, dest_offset);
584 uint8_t expected[16] = { 0, 1, 2, 3, 0, 0, 0, 0, 4, 5, 6, 7, 0, 1, 2, 3 };
585 GetResourcePixels(
586 resource_provider_.get(), context(), id, size, format, result);
587 EXPECT_EQ(0, memcmp(expected, result, pixel_size));
590 gfx::Rect offset_image_rect(gfx::Point(100, 100), size);
591 gfx::Rect source_rect(100, 100, 1, 1);
592 gfx::Vector2d dest_offset(1, 0);
593 resource_provider_->SetPixels(
594 id, image, offset_image_rect, source_rect, dest_offset);
596 uint8_t expected[16] = { 0, 1, 2, 3, 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3 };
597 GetResourcePixels(
598 resource_provider_.get(), context(), id, size, format, result);
599 EXPECT_EQ(0, memcmp(expected, result, pixel_size));
602 resource_provider_->DeleteResource(id);
605 TEST_P(ResourceProviderTest, SimpleUpload) {
606 gfx::Size size(2, 2);
607 ResourceFormat format = RGBA_8888;
608 size_t pixel_size = TextureSizeBytes(size, format);
609 ASSERT_EQ(16U, pixel_size);
611 ResourceId id = resource_provider_->CreateResource(
612 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
614 uint8_t image[16] = {0};
615 resource_provider_->CopyToResource(id, image, size);
617 uint8_t result[16] = {0};
618 uint8_t expected[16] = {0};
619 GetResourcePixels(resource_provider_.get(), context(), id, size, format,
620 result);
621 EXPECT_EQ(0, memcmp(expected, result, pixel_size));
624 for (uint8_t i = 0; i < pixel_size; ++i)
625 image[i] = i;
626 resource_provider_->CopyToResource(id, image, size);
628 uint8_t result[16] = {0};
629 uint8_t expected[16] = {
630 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
631 GetResourcePixels(resource_provider_.get(), context(), id, size, format,
632 result);
633 EXPECT_EQ(0, memcmp(expected, result, pixel_size));
637 TEST_P(ResourceProviderTest, TransferGLResources) {
638 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
639 return;
640 gfx::Size size(1, 1);
641 ResourceFormat format = RGBA_8888;
642 size_t pixel_size = TextureSizeBytes(size, format);
643 ASSERT_EQ(4U, pixel_size);
645 ResourceId id1 = child_resource_provider_->CreateResource(
646 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
647 uint8_t data1[4] = { 1, 2, 3, 4 };
648 child_resource_provider_->CopyToResource(id1, data1, size);
650 ResourceId id2 = child_resource_provider_->CreateResource(
651 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
652 uint8_t data2[4] = { 5, 5, 5, 5 };
653 child_resource_provider_->CopyToResource(id2, data2, size);
655 ResourceId id3 = child_resource_provider_->CreateResource(
656 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
658 ResourceProvider::ScopedWriteLockGpuMemoryBuffer lock(
659 child_resource_provider_.get(), id3);
660 EXPECT_TRUE(lock.GetGpuMemoryBuffer());
663 GLuint external_texture_id = child_context_->createExternalTexture();
665 gpu::Mailbox external_mailbox;
666 child_context_->genMailboxCHROMIUM(external_mailbox.name);
667 child_context_->produceTextureDirectCHROMIUM(
668 external_texture_id, GL_TEXTURE_EXTERNAL_OES, external_mailbox.name);
669 const GLuint external_sync_point = child_context_->insertSyncPoint();
670 ResourceId id4 = child_resource_provider_->CreateResourceFromTextureMailbox(
671 TextureMailbox(external_mailbox, GL_TEXTURE_EXTERNAL_OES,
672 external_sync_point),
673 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback)));
675 ReturnedResourceArray returned_to_child;
676 int child_id =
677 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
679 // Transfer some resources to the parent.
680 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
681 resource_ids_to_transfer.push_back(id1);
682 resource_ids_to_transfer.push_back(id2);
683 resource_ids_to_transfer.push_back(id3);
684 resource_ids_to_transfer.push_back(id4);
685 TransferableResourceArray list;
686 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
687 &list);
688 ASSERT_EQ(4u, list.size());
689 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
690 EXPECT_NE(0u, list[1].mailbox_holder.sync_point);
691 EXPECT_EQ(list[0].mailbox_holder.sync_point,
692 list[1].mailbox_holder.sync_point);
693 EXPECT_NE(0u, list[2].mailbox_holder.sync_point);
694 EXPECT_EQ(list[0].mailbox_holder.sync_point,
695 list[2].mailbox_holder.sync_point);
696 EXPECT_EQ(external_sync_point, list[3].mailbox_holder.sync_point);
697 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
698 list[0].mailbox_holder.texture_target);
699 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
700 list[1].mailbox_holder.texture_target);
701 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
702 list[2].mailbox_holder.texture_target);
703 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_EXTERNAL_OES),
704 list[3].mailbox_holder.texture_target);
705 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
706 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
707 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
708 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id4));
709 resource_provider_->ReceiveFromChild(child_id, list);
710 EXPECT_NE(list[0].mailbox_holder.sync_point,
711 context3d_->last_waited_sync_point());
713 resource_provider_->WaitSyncPointIfNeeded(list[0].id);
714 ResourceProvider::ScopedReadLockGL lock(resource_provider_.get(),
715 list[0].id);
717 EXPECT_EQ(list[0].mailbox_holder.sync_point,
718 context3d_->last_waited_sync_point());
719 ResourceProvider::ResourceIdSet resource_ids_to_receive;
720 resource_ids_to_receive.insert(id1);
721 resource_ids_to_receive.insert(id2);
722 resource_ids_to_receive.insert(id3);
723 resource_ids_to_receive.insert(id4);
724 resource_provider_->DeclareUsedResourcesFromChild(child_id,
725 resource_ids_to_receive);
728 EXPECT_EQ(4u, resource_provider_->num_resources());
729 ResourceProvider::ResourceIdMap resource_map =
730 resource_provider_->GetChildToParentMap(child_id);
731 ResourceId mapped_id1 = resource_map[id1];
732 ResourceId mapped_id2 = resource_map[id2];
733 ResourceId mapped_id3 = resource_map[id3];
734 ResourceId mapped_id4 = resource_map[id4];
735 EXPECT_NE(0u, mapped_id1);
736 EXPECT_NE(0u, mapped_id2);
737 EXPECT_NE(0u, mapped_id3);
738 EXPECT_NE(0u, mapped_id4);
739 EXPECT_FALSE(resource_provider_->InUseByConsumer(id1));
740 EXPECT_FALSE(resource_provider_->InUseByConsumer(id2));
741 EXPECT_FALSE(resource_provider_->InUseByConsumer(id3));
742 EXPECT_FALSE(resource_provider_->InUseByConsumer(id4));
744 uint8_t result[4] = { 0 };
745 GetResourcePixels(
746 resource_provider_.get(), context(), mapped_id1, size, format, result);
747 EXPECT_EQ(0, memcmp(data1, result, pixel_size));
749 GetResourcePixels(
750 resource_provider_.get(), context(), mapped_id2, size, format, result);
751 EXPECT_EQ(0, memcmp(data2, result, pixel_size));
754 // Check that transfering again the same resource from the child to the
755 // parent works.
756 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
757 resource_ids_to_transfer.push_back(id1);
758 resource_ids_to_transfer.push_back(id2);
759 resource_ids_to_transfer.push_back(id3);
760 TransferableResourceArray list;
761 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
762 &list);
763 EXPECT_EQ(3u, list.size());
764 EXPECT_EQ(id1, list[0].id);
765 EXPECT_EQ(id2, list[1].id);
766 EXPECT_EQ(id3, list[2].id);
767 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
768 list[0].mailbox_holder.texture_target);
769 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
770 list[1].mailbox_holder.texture_target);
771 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
772 list[2].mailbox_holder.texture_target);
773 ReturnedResourceArray returned;
774 TransferableResource::ReturnResources(list, &returned);
775 child_resource_provider_->ReceiveReturnsFromParent(returned);
776 // ids were exported twice, we returned them only once, they should still
777 // be in-use.
778 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
779 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
780 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
783 EXPECT_EQ(0u, returned_to_child.size());
785 // Transfer resources back from the parent to the child. Set no resources as
786 // being in use.
787 ResourceProvider::ResourceIdSet no_resources;
788 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
790 ASSERT_EQ(4u, returned_to_child.size());
791 EXPECT_NE(0u, returned_to_child[0].sync_point);
792 EXPECT_NE(0u, returned_to_child[1].sync_point);
793 EXPECT_NE(0u, returned_to_child[2].sync_point);
794 EXPECT_NE(0u, returned_to_child[3].sync_point);
795 EXPECT_FALSE(returned_to_child[0].lost);
796 EXPECT_FALSE(returned_to_child[1].lost);
797 EXPECT_FALSE(returned_to_child[2].lost);
798 EXPECT_FALSE(returned_to_child[3].lost);
799 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
800 returned_to_child.clear();
802 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id1));
803 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id2));
804 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id3));
805 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id4));
808 child_resource_provider_->WaitSyncPointIfNeeded(id1);
809 ResourceProvider::ScopedReadLockGL lock(child_resource_provider_.get(),
810 id1);
811 ASSERT_NE(0U, lock.texture_id());
812 child_context_->bindTexture(GL_TEXTURE_2D, lock.texture_id());
813 child_context_->GetPixels(size, format, result);
814 EXPECT_EQ(0, memcmp(data1, result, pixel_size));
817 child_resource_provider_->WaitSyncPointIfNeeded(id2);
818 ResourceProvider::ScopedReadLockGL lock(child_resource_provider_.get(),
819 id2);
820 ASSERT_NE(0U, lock.texture_id());
821 child_context_->bindTexture(GL_TEXTURE_2D, lock.texture_id());
822 child_context_->GetPixels(size, format, result);
823 EXPECT_EQ(0, memcmp(data2, result, pixel_size));
826 child_resource_provider_->WaitSyncPointIfNeeded(id3);
827 ResourceProvider::ScopedReadLockGL lock(child_resource_provider_.get(),
828 id3);
829 ASSERT_NE(0U, lock.texture_id());
830 child_context_->bindTexture(GL_TEXTURE_2D, lock.texture_id());
833 // Transfer resources to the parent again.
834 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
835 resource_ids_to_transfer.push_back(id1);
836 resource_ids_to_transfer.push_back(id2);
837 resource_ids_to_transfer.push_back(id3);
838 resource_ids_to_transfer.push_back(id4);
839 TransferableResourceArray list;
840 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
841 &list);
842 ASSERT_EQ(4u, list.size());
843 EXPECT_EQ(id1, list[0].id);
844 EXPECT_EQ(id2, list[1].id);
845 EXPECT_EQ(id3, list[2].id);
846 EXPECT_EQ(id4, list[3].id);
847 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
848 EXPECT_NE(0u, list[1].mailbox_holder.sync_point);
849 EXPECT_NE(0u, list[2].mailbox_holder.sync_point);
850 EXPECT_NE(0u, list[3].mailbox_holder.sync_point);
851 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
852 list[0].mailbox_holder.texture_target);
853 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
854 list[1].mailbox_holder.texture_target);
855 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
856 list[2].mailbox_holder.texture_target);
857 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_EXTERNAL_OES),
858 list[3].mailbox_holder.texture_target);
859 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
860 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
861 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
862 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id4));
863 resource_provider_->ReceiveFromChild(child_id, list);
864 ResourceProvider::ResourceIdSet resource_ids_to_receive;
865 resource_ids_to_receive.insert(id1);
866 resource_ids_to_receive.insert(id2);
867 resource_ids_to_receive.insert(id3);
868 resource_ids_to_receive.insert(id4);
869 resource_provider_->DeclareUsedResourcesFromChild(child_id,
870 resource_ids_to_receive);
873 EXPECT_EQ(0u, returned_to_child.size());
875 EXPECT_EQ(4u, resource_provider_->num_resources());
876 resource_provider_->DestroyChild(child_id);
877 EXPECT_EQ(0u, resource_provider_->num_resources());
879 ASSERT_EQ(4u, returned_to_child.size());
880 EXPECT_NE(0u, returned_to_child[0].sync_point);
881 EXPECT_NE(0u, returned_to_child[1].sync_point);
882 EXPECT_NE(0u, returned_to_child[2].sync_point);
883 EXPECT_NE(0u, returned_to_child[3].sync_point);
884 EXPECT_FALSE(returned_to_child[0].lost);
885 EXPECT_FALSE(returned_to_child[1].lost);
886 EXPECT_FALSE(returned_to_child[2].lost);
887 EXPECT_FALSE(returned_to_child[3].lost);
890 class ResourceProviderTestNoSyncPoint : public ResourceProviderTest {
891 public:
892 ResourceProviderTestNoSyncPoint() : ResourceProviderTest(false) {
893 EXPECT_EQ(ResourceProvider::RESOURCE_TYPE_GL_TEXTURE, GetParam());
897 TEST_P(ResourceProviderTestNoSyncPoint, TransferGLResources) {
898 gfx::Size size(1, 1);
899 ResourceFormat format = RGBA_8888;
900 size_t pixel_size = TextureSizeBytes(size, format);
901 ASSERT_EQ(4U, pixel_size);
903 ResourceId id1 = child_resource_provider_->CreateResource(
904 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
905 uint8_t data1[4] = {1, 2, 3, 4};
906 child_resource_provider_->CopyToResource(id1, data1, size);
908 ResourceId id2 = child_resource_provider_->CreateResource(
909 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
911 // Ensure locking the memory buffer doesn't create an unnecessary sync
912 // point.
913 ResourceProvider::ScopedWriteLockGpuMemoryBuffer lock(
914 child_resource_provider_.get(), id2);
915 EXPECT_TRUE(lock.GetGpuMemoryBuffer());
918 GLuint external_texture_id = child_context_->createExternalTexture();
920 // A sync point is specified directly and should be used.
921 gpu::Mailbox external_mailbox;
922 child_context_->genMailboxCHROMIUM(external_mailbox.name);
923 child_context_->produceTextureDirectCHROMIUM(
924 external_texture_id, GL_TEXTURE_EXTERNAL_OES, external_mailbox.name);
925 const GLuint external_sync_point = child_context_->insertSyncPoint();
926 ResourceId id3 = child_resource_provider_->CreateResourceFromTextureMailbox(
927 TextureMailbox(external_mailbox, GL_TEXTURE_EXTERNAL_OES,
928 external_sync_point),
929 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback)));
931 ReturnedResourceArray returned_to_child;
932 int child_id =
933 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
934 resource_provider_->SetChildNeedsSyncPoints(child_id, false);
936 // Transfer some resources to the parent.
937 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
938 resource_ids_to_transfer.push_back(id1);
939 resource_ids_to_transfer.push_back(id2);
940 resource_ids_to_transfer.push_back(id3);
941 TransferableResourceArray list;
942 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
943 &list);
944 ASSERT_EQ(3u, list.size());
945 // Standard resources shouldn't require creating and sending a sync point.
946 EXPECT_EQ(0u, list[0].mailbox_holder.sync_point);
947 EXPECT_EQ(0u, list[1].mailbox_holder.sync_point);
948 // A given sync point should be passed through.
949 EXPECT_EQ(external_sync_point, list[2].mailbox_holder.sync_point);
950 resource_provider_->ReceiveFromChild(child_id, list);
952 ResourceProvider::ResourceIdSet resource_ids_to_receive;
953 resource_ids_to_receive.insert(id1);
954 resource_ids_to_receive.insert(id2);
955 resource_ids_to_receive.insert(id3);
956 resource_provider_->DeclareUsedResourcesFromChild(child_id,
957 resource_ids_to_receive);
961 EXPECT_EQ(0u, returned_to_child.size());
963 // Transfer resources back from the parent to the child. Set no resources as
964 // being in use.
965 ResourceProvider::ResourceIdSet no_resources;
966 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
968 ASSERT_EQ(3u, returned_to_child.size());
969 std::map<ResourceId, unsigned int> returned_sync_points;
970 for (const auto& returned : returned_to_child)
971 returned_sync_points[returned.id] = returned.sync_point;
973 EXPECT_TRUE(returned_sync_points.find(id1) != returned_sync_points.end());
974 // No new sync point should be created transferring back.
975 EXPECT_TRUE(returned_sync_points.find(id1) != returned_sync_points.end());
976 EXPECT_EQ(0u, returned_sync_points[id1]);
977 EXPECT_TRUE(returned_sync_points.find(id2) != returned_sync_points.end());
978 EXPECT_EQ(0u, returned_sync_points[id2]);
979 // Original sync point given should be returned.
980 EXPECT_TRUE(returned_sync_points.find(id3) != returned_sync_points.end());
981 EXPECT_EQ(external_sync_point, returned_sync_points[id3]);
982 EXPECT_FALSE(returned_to_child[0].lost);
983 EXPECT_FALSE(returned_to_child[1].lost);
984 EXPECT_FALSE(returned_to_child[2].lost);
985 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
986 returned_to_child.clear();
989 resource_provider_->DestroyChild(child_id);
992 INSTANTIATE_TEST_CASE_P(
993 ResourceProviderTests,
994 ResourceProviderTestNoSyncPoint,
995 ::testing::Values(ResourceProvider::RESOURCE_TYPE_GL_TEXTURE));
997 TEST_P(ResourceProviderTest, ReadLockCountStopsReturnToChildOrDelete) {
998 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
999 return;
1000 gfx::Size size(1, 1);
1001 ResourceFormat format = RGBA_8888;
1003 ResourceId id1 = child_resource_provider_->CreateResource(
1004 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
1005 uint8_t data1[4] = {1, 2, 3, 4};
1006 child_resource_provider_->CopyToResource(id1, data1, size);
1008 ReturnedResourceArray returned_to_child;
1009 int child_id =
1010 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1012 // Transfer some resources to the parent.
1013 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1014 resource_ids_to_transfer.push_back(id1);
1015 TransferableResourceArray list;
1016 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1017 &list);
1018 ASSERT_EQ(1u, list.size());
1019 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1021 resource_provider_->ReceiveFromChild(child_id, list);
1023 resource_provider_->WaitSyncPointIfNeeded(list[0].id);
1024 ResourceProvider::ScopedReadLockGL lock(resource_provider_.get(),
1025 list[0].id);
1027 resource_provider_->DeclareUsedResourcesFromChild(
1028 child_id, ResourceProvider::ResourceIdSet());
1029 EXPECT_EQ(0u, returned_to_child.size());
1032 EXPECT_EQ(1u, returned_to_child.size());
1033 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
1036 child_resource_provider_->WaitSyncPointIfNeeded(id1);
1037 ResourceProvider::ScopedReadLockGL lock(child_resource_provider_.get(),
1038 id1);
1039 child_resource_provider_->DeleteResource(id1);
1040 EXPECT_EQ(1u, child_resource_provider_->num_resources());
1041 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1044 EXPECT_EQ(0u, child_resource_provider_->num_resources());
1045 resource_provider_->DestroyChild(child_id);
1048 TEST_P(ResourceProviderTest, AllowOverlayTransfersToParent) {
1049 // Overlays only supported on the GL path.
1050 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
1051 return;
1053 uint32 sync_point = 0;
1054 TextureMailbox mailbox(gpu::Mailbox::Generate(), GL_TEXTURE_2D, sync_point);
1055 mailbox.set_allow_overlay(true);
1056 scoped_ptr<SingleReleaseCallbackImpl> release_callback =
1057 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback));
1058 ResourceId id1 = child_resource_provider_->CreateResourceFromTextureMailbox(
1059 mailbox, release_callback.Pass());
1061 TextureMailbox mailbox2(gpu::Mailbox::Generate(), GL_TEXTURE_2D, sync_point);
1062 mailbox2.set_allow_overlay(false);
1063 scoped_ptr<SingleReleaseCallbackImpl> release_callback2 =
1064 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback));
1065 ResourceId id2 = child_resource_provider_->CreateResourceFromTextureMailbox(
1066 mailbox2, release_callback2.Pass());
1068 ReturnedResourceArray returned_to_child;
1069 int child_id =
1070 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1072 // Transfer some resources to the parent.
1073 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1074 resource_ids_to_transfer.push_back(id1);
1075 resource_ids_to_transfer.push_back(id2);
1076 TransferableResourceArray list;
1077 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1078 &list);
1079 ASSERT_EQ(2u, list.size());
1080 resource_provider_->ReceiveFromChild(child_id, list);
1081 EXPECT_TRUE(resource_provider_->AllowOverlay(list[0].id));
1082 EXPECT_FALSE(resource_provider_->AllowOverlay(list[1].id));
1084 resource_provider_->DeclareUsedResourcesFromChild(
1085 child_id, ResourceProvider::ResourceIdSet());
1087 EXPECT_EQ(2u, returned_to_child.size());
1088 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
1090 child_resource_provider_->DeleteResource(id1);
1091 child_resource_provider_->DeleteResource(id2);
1092 EXPECT_EQ(0u, child_resource_provider_->num_resources());
1094 resource_provider_->DestroyChild(child_id);
1097 TEST_P(ResourceProviderTest, TransferSoftwareResources) {
1098 if (GetParam() != ResourceProvider::RESOURCE_TYPE_BITMAP)
1099 return;
1101 gfx::Size size(1, 1);
1102 ResourceFormat format = RGBA_8888;
1103 size_t pixel_size = TextureSizeBytes(size, format);
1104 ASSERT_EQ(4U, pixel_size);
1106 ResourceId id1 = child_resource_provider_->CreateResource(
1107 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
1108 uint8_t data1[4] = { 1, 2, 3, 4 };
1109 child_resource_provider_->CopyToResource(id1, data1, size);
1111 ResourceId id2 = child_resource_provider_->CreateResource(
1112 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
1113 uint8_t data2[4] = { 5, 5, 5, 5 };
1114 child_resource_provider_->CopyToResource(id2, data2, size);
1116 scoped_ptr<SharedBitmap> shared_bitmap(CreateAndFillSharedBitmap(
1117 shared_bitmap_manager_.get(), gfx::Size(1, 1), 0));
1118 SharedBitmap* shared_bitmap_ptr = shared_bitmap.get();
1119 ResourceId id3 = child_resource_provider_->CreateResourceFromTextureMailbox(
1120 TextureMailbox(shared_bitmap_ptr, gfx::Size(1, 1)),
1121 SingleReleaseCallbackImpl::Create(base::Bind(
1122 &SharedBitmapReleaseCallback, base::Passed(&shared_bitmap))));
1124 ReturnedResourceArray returned_to_child;
1125 int child_id =
1126 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1128 // Transfer some resources to the parent.
1129 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1130 resource_ids_to_transfer.push_back(id1);
1131 resource_ids_to_transfer.push_back(id2);
1132 resource_ids_to_transfer.push_back(id3);
1133 TransferableResourceArray list;
1134 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1135 &list);
1136 ASSERT_EQ(3u, list.size());
1137 EXPECT_EQ(0u, list[0].mailbox_holder.sync_point);
1138 EXPECT_EQ(0u, list[1].mailbox_holder.sync_point);
1139 EXPECT_EQ(0u, list[2].mailbox_holder.sync_point);
1140 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1141 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
1142 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
1143 resource_provider_->ReceiveFromChild(child_id, list);
1144 ResourceProvider::ResourceIdSet resource_ids_to_receive;
1145 resource_ids_to_receive.insert(id1);
1146 resource_ids_to_receive.insert(id2);
1147 resource_ids_to_receive.insert(id3);
1148 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1149 resource_ids_to_receive);
1152 EXPECT_EQ(3u, resource_provider_->num_resources());
1153 ResourceProvider::ResourceIdMap resource_map =
1154 resource_provider_->GetChildToParentMap(child_id);
1155 ResourceId mapped_id1 = resource_map[id1];
1156 ResourceId mapped_id2 = resource_map[id2];
1157 ResourceId mapped_id3 = resource_map[id3];
1158 EXPECT_NE(0u, mapped_id1);
1159 EXPECT_NE(0u, mapped_id2);
1160 EXPECT_NE(0u, mapped_id3);
1161 EXPECT_FALSE(resource_provider_->InUseByConsumer(id1));
1162 EXPECT_FALSE(resource_provider_->InUseByConsumer(id2));
1163 EXPECT_FALSE(resource_provider_->InUseByConsumer(id3));
1165 uint8_t result[4] = { 0 };
1166 GetResourcePixels(
1167 resource_provider_.get(), context(), mapped_id1, size, format, result);
1168 EXPECT_EQ(0, memcmp(data1, result, pixel_size));
1170 GetResourcePixels(
1171 resource_provider_.get(), context(), mapped_id2, size, format, result);
1172 EXPECT_EQ(0, memcmp(data2, result, pixel_size));
1175 // Check that transfering again the same resource from the child to the
1176 // parent works.
1177 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1178 resource_ids_to_transfer.push_back(id1);
1179 resource_ids_to_transfer.push_back(id2);
1180 TransferableResourceArray list;
1181 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1182 &list);
1183 EXPECT_EQ(2u, list.size());
1184 EXPECT_EQ(id1, list[0].id);
1185 EXPECT_EQ(id2, list[1].id);
1186 ReturnedResourceArray returned;
1187 TransferableResource::ReturnResources(list, &returned);
1188 child_resource_provider_->ReceiveReturnsFromParent(returned);
1189 // ids were exported twice, we returned them only once, they should still
1190 // be in-use.
1191 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1192 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
1195 EXPECT_EQ(0u, returned_to_child.size());
1197 // Transfer resources back from the parent to the child. Set no resources as
1198 // being in use.
1199 ResourceProvider::ResourceIdSet no_resources;
1200 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
1202 ASSERT_EQ(3u, returned_to_child.size());
1203 EXPECT_EQ(0u, returned_to_child[0].sync_point);
1204 EXPECT_EQ(0u, returned_to_child[1].sync_point);
1205 EXPECT_EQ(0u, returned_to_child[2].sync_point);
1206 std::set<ResourceId> expected_ids;
1207 expected_ids.insert(id1);
1208 expected_ids.insert(id2);
1209 expected_ids.insert(id3);
1210 std::set<ResourceId> returned_ids;
1211 for (unsigned i = 0; i < 3; i++)
1212 returned_ids.insert(returned_to_child[i].id);
1213 EXPECT_EQ(expected_ids, returned_ids);
1214 EXPECT_FALSE(returned_to_child[0].lost);
1215 EXPECT_FALSE(returned_to_child[1].lost);
1216 EXPECT_FALSE(returned_to_child[2].lost);
1217 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
1218 returned_to_child.clear();
1220 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id1));
1221 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id2));
1222 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id3));
1225 ResourceProvider::ScopedReadLockSoftware lock(
1226 child_resource_provider_.get(), id1);
1227 const SkBitmap* sk_bitmap = lock.sk_bitmap();
1228 EXPECT_EQ(sk_bitmap->width(), size.width());
1229 EXPECT_EQ(sk_bitmap->height(), size.height());
1230 EXPECT_EQ(0, memcmp(data1, sk_bitmap->getPixels(), pixel_size));
1233 ResourceProvider::ScopedReadLockSoftware lock(
1234 child_resource_provider_.get(), id2);
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(data2, sk_bitmap->getPixels(), pixel_size));
1241 // Transfer resources to the parent again.
1242 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1243 resource_ids_to_transfer.push_back(id1);
1244 resource_ids_to_transfer.push_back(id2);
1245 resource_ids_to_transfer.push_back(id3);
1246 TransferableResourceArray list;
1247 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1248 &list);
1249 ASSERT_EQ(3u, list.size());
1250 EXPECT_EQ(id1, list[0].id);
1251 EXPECT_EQ(id2, list[1].id);
1252 EXPECT_EQ(id3, list[2].id);
1253 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1254 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
1255 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
1256 resource_provider_->ReceiveFromChild(child_id, list);
1257 ResourceProvider::ResourceIdSet resource_ids_to_receive;
1258 resource_ids_to_receive.insert(id1);
1259 resource_ids_to_receive.insert(id2);
1260 resource_ids_to_receive.insert(id3);
1261 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1262 resource_ids_to_receive);
1265 EXPECT_EQ(0u, returned_to_child.size());
1267 EXPECT_EQ(3u, resource_provider_->num_resources());
1268 resource_provider_->DestroyChild(child_id);
1269 EXPECT_EQ(0u, resource_provider_->num_resources());
1271 ASSERT_EQ(3u, returned_to_child.size());
1272 EXPECT_EQ(0u, returned_to_child[0].sync_point);
1273 EXPECT_EQ(0u, returned_to_child[1].sync_point);
1274 EXPECT_EQ(0u, returned_to_child[2].sync_point);
1275 std::set<ResourceId> expected_ids;
1276 expected_ids.insert(id1);
1277 expected_ids.insert(id2);
1278 expected_ids.insert(id3);
1279 std::set<ResourceId> returned_ids;
1280 for (unsigned i = 0; i < 3; i++)
1281 returned_ids.insert(returned_to_child[i].id);
1282 EXPECT_EQ(expected_ids, returned_ids);
1283 EXPECT_FALSE(returned_to_child[0].lost);
1284 EXPECT_FALSE(returned_to_child[1].lost);
1285 EXPECT_FALSE(returned_to_child[2].lost);
1288 TEST_P(ResourceProviderTest, TransferGLToSoftware) {
1289 if (GetParam() != ResourceProvider::RESOURCE_TYPE_BITMAP)
1290 return;
1292 scoped_ptr<ResourceProviderContext> child_context_owned(
1293 ResourceProviderContext::Create(shared_data_.get()));
1295 FakeOutputSurfaceClient child_output_surface_client;
1296 scoped_ptr<OutputSurface> child_output_surface(
1297 FakeOutputSurface::Create3d(child_context_owned.Pass()));
1298 CHECK(child_output_surface->BindToClient(&child_output_surface_client));
1300 scoped_ptr<ResourceProvider> child_resource_provider(ResourceProvider::Create(
1301 child_output_surface.get(), shared_bitmap_manager_.get(),
1302 gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false));
1304 gfx::Size size(1, 1);
1305 ResourceFormat format = RGBA_8888;
1306 size_t pixel_size = TextureSizeBytes(size, format);
1307 ASSERT_EQ(4U, pixel_size);
1309 ResourceId id1 = child_resource_provider->CreateResource(
1310 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
1311 uint8_t data1[4] = { 1, 2, 3, 4 };
1312 child_resource_provider->CopyToResource(id1, data1, size);
1314 ReturnedResourceArray returned_to_child;
1315 int child_id =
1316 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1318 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1319 resource_ids_to_transfer.push_back(id1);
1320 TransferableResourceArray list;
1321 child_resource_provider->PrepareSendToParent(resource_ids_to_transfer,
1322 &list);
1323 ASSERT_EQ(1u, list.size());
1324 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
1325 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
1326 list[0].mailbox_holder.texture_target);
1327 EXPECT_TRUE(child_resource_provider->InUseByConsumer(id1));
1328 resource_provider_->ReceiveFromChild(child_id, list);
1331 EXPECT_EQ(0u, resource_provider_->num_resources());
1332 ASSERT_EQ(1u, returned_to_child.size());
1333 EXPECT_EQ(returned_to_child[0].id, id1);
1334 ResourceProvider::ResourceIdMap resource_map =
1335 resource_provider_->GetChildToParentMap(child_id);
1336 ResourceId mapped_id1 = resource_map[id1];
1337 EXPECT_EQ(0u, mapped_id1);
1339 resource_provider_->DestroyChild(child_id);
1340 EXPECT_EQ(0u, resource_provider_->num_resources());
1342 ASSERT_EQ(1u, returned_to_child.size());
1343 EXPECT_FALSE(returned_to_child[0].lost);
1346 TEST_P(ResourceProviderTest, TransferInvalidSoftware) {
1347 if (GetParam() != ResourceProvider::RESOURCE_TYPE_BITMAP)
1348 return;
1350 gfx::Size size(1, 1);
1351 ResourceFormat format = RGBA_8888;
1352 size_t pixel_size = TextureSizeBytes(size, format);
1353 ASSERT_EQ(4U, pixel_size);
1355 ResourceId id1 = child_resource_provider_->CreateResource(
1356 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
1357 uint8_t data1[4] = { 1, 2, 3, 4 };
1358 child_resource_provider_->CopyToResource(id1, data1, size);
1360 ReturnedResourceArray returned_to_child;
1361 int child_id =
1362 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1364 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1365 resource_ids_to_transfer.push_back(id1);
1366 TransferableResourceArray list;
1367 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1368 &list);
1369 ASSERT_EQ(1u, list.size());
1370 // Make invalid.
1371 list[0].mailbox_holder.mailbox.name[1] = 5;
1372 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1373 resource_provider_->ReceiveFromChild(child_id, list);
1376 EXPECT_EQ(1u, resource_provider_->num_resources());
1377 EXPECT_EQ(0u, returned_to_child.size());
1379 ResourceProvider::ResourceIdMap resource_map =
1380 resource_provider_->GetChildToParentMap(child_id);
1381 ResourceId mapped_id1 = resource_map[id1];
1382 EXPECT_NE(0u, mapped_id1);
1384 ResourceProvider::ScopedReadLockSoftware lock(resource_provider_.get(),
1385 mapped_id1);
1386 EXPECT_FALSE(lock.valid());
1389 resource_provider_->DestroyChild(child_id);
1390 EXPECT_EQ(0u, resource_provider_->num_resources());
1392 ASSERT_EQ(1u, returned_to_child.size());
1393 EXPECT_FALSE(returned_to_child[0].lost);
1396 TEST_P(ResourceProviderTest, DeleteExportedResources) {
1397 gfx::Size size(1, 1);
1398 ResourceFormat format = RGBA_8888;
1399 size_t pixel_size = TextureSizeBytes(size, format);
1400 ASSERT_EQ(4U, pixel_size);
1402 ResourceId id1 = child_resource_provider_->CreateResource(
1403 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
1404 uint8_t data1[4] = { 1, 2, 3, 4 };
1405 child_resource_provider_->CopyToResource(id1, data1, size);
1407 ResourceId id2 = child_resource_provider_->CreateResource(
1408 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
1409 uint8_t data2[4] = {5, 5, 5, 5};
1410 child_resource_provider_->CopyToResource(id2, data2, size);
1412 ReturnedResourceArray returned_to_child;
1413 int child_id =
1414 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1416 // Transfer some resources to the parent.
1417 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1418 resource_ids_to_transfer.push_back(id1);
1419 resource_ids_to_transfer.push_back(id2);
1420 TransferableResourceArray list;
1421 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1422 &list);
1423 ASSERT_EQ(2u, list.size());
1424 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) {
1425 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
1426 EXPECT_NE(0u, list[1].mailbox_holder.sync_point);
1428 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1429 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
1430 resource_provider_->ReceiveFromChild(child_id, list);
1431 ResourceProvider::ResourceIdSet resource_ids_to_receive;
1432 resource_ids_to_receive.insert(id1);
1433 resource_ids_to_receive.insert(id2);
1434 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1435 resource_ids_to_receive);
1438 EXPECT_EQ(2u, resource_provider_->num_resources());
1439 ResourceProvider::ResourceIdMap resource_map =
1440 resource_provider_->GetChildToParentMap(child_id);
1441 ResourceId mapped_id1 = resource_map[id1];
1442 ResourceId mapped_id2 = resource_map[id2];
1443 EXPECT_NE(0u, mapped_id1);
1444 EXPECT_NE(0u, mapped_id2);
1445 EXPECT_FALSE(resource_provider_->InUseByConsumer(id1));
1446 EXPECT_FALSE(resource_provider_->InUseByConsumer(id2));
1449 // The parent transfers the resources to the grandparent.
1450 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1451 resource_ids_to_transfer.push_back(mapped_id1);
1452 resource_ids_to_transfer.push_back(mapped_id2);
1453 TransferableResourceArray list;
1454 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
1456 ASSERT_EQ(2u, list.size());
1457 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) {
1458 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
1459 EXPECT_NE(0u, list[1].mailbox_holder.sync_point);
1461 EXPECT_TRUE(resource_provider_->InUseByConsumer(id1));
1462 EXPECT_TRUE(resource_provider_->InUseByConsumer(id2));
1464 // Release the resource in the parent. Set no resources as being in use. The
1465 // resources are exported so that can't be transferred back yet.
1466 ResourceProvider::ResourceIdSet no_resources;
1467 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
1469 EXPECT_EQ(0u, returned_to_child.size());
1470 EXPECT_EQ(2u, resource_provider_->num_resources());
1472 // Return the resources from the grandparent to the parent. They should be
1473 // returned to the child then.
1474 EXPECT_EQ(2u, list.size());
1475 EXPECT_EQ(mapped_id1, list[0].id);
1476 EXPECT_EQ(mapped_id2, list[1].id);
1477 ReturnedResourceArray returned;
1478 TransferableResource::ReturnResources(list, &returned);
1479 resource_provider_->ReceiveReturnsFromParent(returned);
1481 EXPECT_EQ(0u, resource_provider_->num_resources());
1482 ASSERT_EQ(2u, returned_to_child.size());
1483 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) {
1484 EXPECT_NE(0u, returned_to_child[0].sync_point);
1485 EXPECT_NE(0u, returned_to_child[1].sync_point);
1487 EXPECT_FALSE(returned_to_child[0].lost);
1488 EXPECT_FALSE(returned_to_child[1].lost);
1492 TEST_P(ResourceProviderTest, DestroyChildWithExportedResources) {
1493 gfx::Size size(1, 1);
1494 ResourceFormat format = RGBA_8888;
1495 size_t pixel_size = TextureSizeBytes(size, format);
1496 ASSERT_EQ(4U, pixel_size);
1498 ResourceId id1 = child_resource_provider_->CreateResource(
1499 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
1500 uint8_t data1[4] = {1, 2, 3, 4};
1501 child_resource_provider_->CopyToResource(id1, data1, size);
1503 ResourceId id2 = child_resource_provider_->CreateResource(
1504 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
1505 uint8_t data2[4] = {5, 5, 5, 5};
1506 child_resource_provider_->CopyToResource(id2, data2, size);
1508 ReturnedResourceArray returned_to_child;
1509 int child_id =
1510 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1512 // Transfer some resources to the parent.
1513 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1514 resource_ids_to_transfer.push_back(id1);
1515 resource_ids_to_transfer.push_back(id2);
1516 TransferableResourceArray list;
1517 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1518 &list);
1519 ASSERT_EQ(2u, list.size());
1520 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) {
1521 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
1522 EXPECT_NE(0u, list[1].mailbox_holder.sync_point);
1524 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1525 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
1526 resource_provider_->ReceiveFromChild(child_id, list);
1527 ResourceProvider::ResourceIdSet resource_ids_to_receive;
1528 resource_ids_to_receive.insert(id1);
1529 resource_ids_to_receive.insert(id2);
1530 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1531 resource_ids_to_receive);
1534 EXPECT_EQ(2u, resource_provider_->num_resources());
1535 ResourceProvider::ResourceIdMap resource_map =
1536 resource_provider_->GetChildToParentMap(child_id);
1537 ResourceId mapped_id1 = resource_map[id1];
1538 ResourceId mapped_id2 = resource_map[id2];
1539 EXPECT_NE(0u, mapped_id1);
1540 EXPECT_NE(0u, mapped_id2);
1541 EXPECT_FALSE(resource_provider_->InUseByConsumer(id1));
1542 EXPECT_FALSE(resource_provider_->InUseByConsumer(id2));
1545 // The parent transfers the resources to the grandparent.
1546 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1547 resource_ids_to_transfer.push_back(mapped_id1);
1548 resource_ids_to_transfer.push_back(mapped_id2);
1549 TransferableResourceArray list;
1550 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
1552 ASSERT_EQ(2u, list.size());
1553 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) {
1554 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
1555 EXPECT_NE(0u, list[1].mailbox_holder.sync_point);
1557 EXPECT_TRUE(resource_provider_->InUseByConsumer(id1));
1558 EXPECT_TRUE(resource_provider_->InUseByConsumer(id2));
1560 // Release the resource in the parent. Set no resources as being in use. The
1561 // resources are exported so that can't be transferred back yet.
1562 ResourceProvider::ResourceIdSet no_resources;
1563 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
1565 // Destroy the child, the resources should not be returned yet.
1566 EXPECT_EQ(0u, returned_to_child.size());
1567 EXPECT_EQ(2u, resource_provider_->num_resources());
1569 resource_provider_->DestroyChild(child_id);
1571 EXPECT_EQ(2u, resource_provider_->num_resources());
1572 ASSERT_EQ(0u, returned_to_child.size());
1574 // Return a resource from the grandparent, it should be returned at this
1575 // point.
1576 EXPECT_EQ(2u, list.size());
1577 EXPECT_EQ(mapped_id1, list[0].id);
1578 EXPECT_EQ(mapped_id2, list[1].id);
1579 TransferableResourceArray return_list;
1580 return_list.push_back(list[1]);
1581 list.pop_back();
1582 ReturnedResourceArray returned;
1583 TransferableResource::ReturnResources(return_list, &returned);
1584 resource_provider_->ReceiveReturnsFromParent(returned);
1586 EXPECT_EQ(1u, resource_provider_->num_resources());
1587 ASSERT_EQ(1u, returned_to_child.size());
1588 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) {
1589 EXPECT_NE(0u, returned_to_child[0].sync_point);
1591 EXPECT_FALSE(returned_to_child[0].lost);
1592 returned_to_child.clear();
1594 // Destroy the parent resource provider. The resource that's left should be
1595 // lost at this point, and returned.
1596 resource_provider_ = nullptr;
1597 ASSERT_EQ(1u, returned_to_child.size());
1598 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) {
1599 EXPECT_NE(0u, returned_to_child[0].sync_point);
1601 EXPECT_TRUE(returned_to_child[0].lost);
1605 TEST_P(ResourceProviderTest, DeleteTransferredResources) {
1606 gfx::Size size(1, 1);
1607 ResourceFormat format = RGBA_8888;
1608 size_t pixel_size = TextureSizeBytes(size, format);
1609 ASSERT_EQ(4U, pixel_size);
1611 ResourceId id = child_resource_provider_->CreateResource(
1612 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
1613 uint8_t data[4] = { 1, 2, 3, 4 };
1614 child_resource_provider_->CopyToResource(id, data, size);
1616 ReturnedResourceArray returned_to_child;
1617 int child_id =
1618 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1620 // Transfer some resource to the parent.
1621 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1622 resource_ids_to_transfer.push_back(id);
1623 TransferableResourceArray list;
1624 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1625 &list);
1626 ASSERT_EQ(1u, list.size());
1627 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
1628 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
1629 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id));
1630 resource_provider_->ReceiveFromChild(child_id, list);
1631 ResourceProvider::ResourceIdSet resource_ids_to_receive;
1632 resource_ids_to_receive.insert(id);
1633 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1634 resource_ids_to_receive);
1637 // Delete textures in the child, while they are transfered.
1638 child_resource_provider_->DeleteResource(id);
1639 EXPECT_EQ(1u, child_resource_provider_->num_resources());
1641 EXPECT_EQ(0u, returned_to_child.size());
1643 // Transfer resources back from the parent to the child. Set no resources as
1644 // being in use.
1645 ResourceProvider::ResourceIdSet no_resources;
1646 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
1648 ASSERT_EQ(1u, returned_to_child.size());
1649 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
1650 EXPECT_NE(0u, returned_to_child[0].sync_point);
1651 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
1653 EXPECT_EQ(0u, child_resource_provider_->num_resources());
1656 TEST_P(ResourceProviderTest, UnuseTransferredResources) {
1657 gfx::Size size(1, 1);
1658 ResourceFormat format = RGBA_8888;
1659 size_t pixel_size = TextureSizeBytes(size, format);
1660 ASSERT_EQ(4U, pixel_size);
1662 ResourceId id = child_resource_provider_->CreateResource(
1663 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
1664 uint8_t data[4] = {1, 2, 3, 4};
1665 child_resource_provider_->CopyToResource(id, data, size);
1667 ReturnedResourceArray returned_to_child;
1668 int child_id =
1669 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1670 const ResourceProvider::ResourceIdMap& map =
1671 resource_provider_->GetChildToParentMap(child_id);
1673 // Transfer some resource to the parent.
1674 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1675 resource_ids_to_transfer.push_back(id);
1676 TransferableResourceArray list;
1677 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1678 &list);
1679 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id));
1680 resource_provider_->ReceiveFromChild(child_id, list);
1681 ResourceProvider::ResourceIdSet resource_ids_to_receive;
1682 resource_ids_to_receive.insert(id);
1683 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1684 resource_ids_to_receive);
1686 TransferableResourceArray sent_to_top_level;
1688 // Parent transfers to top-level.
1689 ASSERT_TRUE(map.find(id) != map.end());
1690 ResourceId parent_id = map.find(id)->second;
1691 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1692 resource_ids_to_transfer.push_back(parent_id);
1693 resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1694 &sent_to_top_level);
1695 EXPECT_TRUE(resource_provider_->InUseByConsumer(parent_id));
1698 // Stop using resource.
1699 ResourceProvider::ResourceIdSet empty;
1700 resource_provider_->DeclareUsedResourcesFromChild(child_id, empty);
1701 // Resource is not yet returned to the child, since it's in use by the
1702 // top-level.
1703 EXPECT_TRUE(returned_to_child.empty());
1706 // Send the resource to the parent again.
1707 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1708 resource_ids_to_transfer.push_back(id);
1709 TransferableResourceArray list;
1710 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1711 &list);
1712 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id));
1713 resource_provider_->ReceiveFromChild(child_id, list);
1714 ResourceProvider::ResourceIdSet resource_ids_to_receive;
1715 resource_ids_to_receive.insert(id);
1716 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1717 resource_ids_to_receive);
1720 // Receive returns back from top-level.
1721 ReturnedResourceArray returned;
1722 TransferableResource::ReturnResources(sent_to_top_level, &returned);
1723 resource_provider_->ReceiveReturnsFromParent(returned);
1724 // Resource is still not yet returned to the child, since it's declared used
1725 // in the parent.
1726 EXPECT_TRUE(returned_to_child.empty());
1727 ASSERT_TRUE(map.find(id) != map.end());
1728 ResourceId parent_id = map.find(id)->second;
1729 EXPECT_FALSE(resource_provider_->InUseByConsumer(parent_id));
1732 sent_to_top_level.clear();
1733 // Parent transfers again to top-level.
1734 ASSERT_TRUE(map.find(id) != map.end());
1735 ResourceId parent_id = map.find(id)->second;
1736 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1737 resource_ids_to_transfer.push_back(parent_id);
1738 resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1739 &sent_to_top_level);
1740 EXPECT_TRUE(resource_provider_->InUseByConsumer(parent_id));
1743 // Receive returns back from top-level.
1744 ReturnedResourceArray returned;
1745 TransferableResource::ReturnResources(sent_to_top_level, &returned);
1746 resource_provider_->ReceiveReturnsFromParent(returned);
1747 // Resource is still not yet returned to the child, since it's still
1748 // declared used in the parent.
1749 EXPECT_TRUE(returned_to_child.empty());
1750 ASSERT_TRUE(map.find(id) != map.end());
1751 ResourceId parent_id = map.find(id)->second;
1752 EXPECT_FALSE(resource_provider_->InUseByConsumer(parent_id));
1755 // Stop using resource.
1756 ResourceProvider::ResourceIdSet empty;
1757 resource_provider_->DeclareUsedResourcesFromChild(child_id, empty);
1758 // Resource should have been returned to the child, since it's no longer in
1759 // use by the top-level.
1760 ASSERT_EQ(1u, returned_to_child.size());
1761 EXPECT_EQ(id, returned_to_child[0].id);
1762 EXPECT_EQ(2, returned_to_child[0].count);
1763 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
1764 returned_to_child.clear();
1765 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id));
1769 class ResourceProviderTestTextureFilters : public ResourceProviderTest {
1770 public:
1771 static void RunTest(GLenum child_filter, GLenum parent_filter) {
1772 scoped_ptr<TextureStateTrackingContext> child_context_owned(
1773 new TextureStateTrackingContext);
1774 TextureStateTrackingContext* child_context = child_context_owned.get();
1776 FakeOutputSurfaceClient child_output_surface_client;
1777 scoped_ptr<OutputSurface> child_output_surface(
1778 FakeOutputSurface::Create3d(child_context_owned.Pass()));
1779 CHECK(child_output_surface->BindToClient(&child_output_surface_client));
1780 scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
1781 new TestSharedBitmapManager());
1783 scoped_ptr<ResourceProvider> child_resource_provider(
1784 ResourceProvider::Create(child_output_surface.get(),
1785 shared_bitmap_manager.get(), NULL, NULL, 0,
1786 false, 1, false));
1788 scoped_ptr<TextureStateTrackingContext> parent_context_owned(
1789 new TextureStateTrackingContext);
1790 TextureStateTrackingContext* parent_context = parent_context_owned.get();
1792 FakeOutputSurfaceClient parent_output_surface_client;
1793 scoped_ptr<OutputSurface> parent_output_surface(
1794 FakeOutputSurface::Create3d(parent_context_owned.Pass()));
1795 CHECK(parent_output_surface->BindToClient(&parent_output_surface_client));
1797 scoped_ptr<ResourceProvider> parent_resource_provider(
1798 ResourceProvider::Create(parent_output_surface.get(),
1799 shared_bitmap_manager.get(), NULL, NULL, 0,
1800 false, 1, false));
1802 gfx::Size size(1, 1);
1803 ResourceFormat format = RGBA_8888;
1804 int child_texture_id = 1;
1805 int parent_texture_id = 2;
1807 size_t pixel_size = TextureSizeBytes(size, format);
1808 ASSERT_EQ(4U, pixel_size);
1810 ResourceId id = child_resource_provider->CreateResource(
1811 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE,
1812 format);
1814 // The new texture is created with GL_LINEAR.
1815 EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, child_texture_id))
1816 .Times(2); // Once to create and once to allocate.
1817 EXPECT_CALL(*child_context,
1818 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
1819 EXPECT_CALL(*child_context,
1820 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
1821 EXPECT_CALL(
1822 *child_context,
1823 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
1824 EXPECT_CALL(
1825 *child_context,
1826 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
1827 EXPECT_CALL(*child_context,
1828 texParameteri(GL_TEXTURE_2D,
1829 GL_TEXTURE_POOL_CHROMIUM,
1830 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM));
1831 child_resource_provider->AllocateForTesting(id);
1832 Mock::VerifyAndClearExpectations(child_context);
1834 uint8_t data[4] = { 1, 2, 3, 4 };
1836 EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, child_texture_id));
1837 child_resource_provider->CopyToResource(id, data, size);
1838 Mock::VerifyAndClearExpectations(child_context);
1840 // The texture is set to |child_filter| in the child.
1841 EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, child_texture_id));
1842 if (child_filter != GL_LINEAR) {
1843 EXPECT_CALL(
1844 *child_context,
1845 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, child_filter));
1846 EXPECT_CALL(
1847 *child_context,
1848 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, child_filter));
1850 SetResourceFilter(child_resource_provider.get(), id, child_filter);
1851 Mock::VerifyAndClearExpectations(child_context);
1853 ReturnedResourceArray returned_to_child;
1854 int child_id = parent_resource_provider->CreateChild(
1855 GetReturnCallback(&returned_to_child));
1857 // Transfer some resource to the parent.
1858 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1859 resource_ids_to_transfer.push_back(id);
1860 TransferableResourceArray list;
1862 EXPECT_CALL(*child_context,
1863 produceTextureDirectCHROMIUM(_, GL_TEXTURE_2D, _));
1864 EXPECT_CALL(*child_context, insertSyncPoint());
1865 child_resource_provider->PrepareSendToParent(resource_ids_to_transfer,
1866 &list);
1867 Mock::VerifyAndClearExpectations(child_context);
1869 ASSERT_EQ(1u, list.size());
1870 EXPECT_EQ(static_cast<unsigned>(child_filter), list[0].filter);
1872 EXPECT_CALL(*parent_context,
1873 createAndConsumeTextureCHROMIUM(GL_TEXTURE_2D, _))
1874 .WillOnce(Return(parent_texture_id));
1876 parent_resource_provider->ReceiveFromChild(child_id, list);
1878 parent_resource_provider->WaitSyncPointIfNeeded(list[0].id);
1879 ResourceProvider::ScopedReadLockGL lock(parent_resource_provider.get(),
1880 list[0].id);
1882 Mock::VerifyAndClearExpectations(parent_context);
1884 ResourceProvider::ResourceIdSet resource_ids_to_receive;
1885 resource_ids_to_receive.insert(id);
1886 parent_resource_provider->DeclareUsedResourcesFromChild(
1887 child_id, resource_ids_to_receive);
1888 Mock::VerifyAndClearExpectations(parent_context);
1890 ResourceProvider::ResourceIdMap resource_map =
1891 parent_resource_provider->GetChildToParentMap(child_id);
1892 ResourceId mapped_id = resource_map[id];
1893 EXPECT_NE(0u, mapped_id);
1895 // The texture is set to |parent_filter| in the parent.
1896 EXPECT_CALL(*parent_context, bindTexture(GL_TEXTURE_2D, parent_texture_id));
1897 EXPECT_CALL(
1898 *parent_context,
1899 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, parent_filter));
1900 EXPECT_CALL(
1901 *parent_context,
1902 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, parent_filter));
1903 SetResourceFilter(parent_resource_provider.get(), mapped_id, parent_filter);
1904 Mock::VerifyAndClearExpectations(parent_context);
1906 // The texture should be reset to |child_filter| in the parent when it is
1907 // returned, since that is how it was received.
1908 EXPECT_CALL(*parent_context, bindTexture(GL_TEXTURE_2D, parent_texture_id));
1909 EXPECT_CALL(
1910 *parent_context,
1911 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, child_filter));
1912 EXPECT_CALL(
1913 *parent_context,
1914 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, child_filter));
1917 EXPECT_EQ(0u, returned_to_child.size());
1919 // Transfer resources back from the parent to the child. Set no resources
1920 // as being in use.
1921 ResourceProvider::ResourceIdSet no_resources;
1922 EXPECT_CALL(*parent_context, insertSyncPoint());
1923 parent_resource_provider->DeclareUsedResourcesFromChild(child_id,
1924 no_resources);
1925 Mock::VerifyAndClearExpectations(parent_context);
1927 ASSERT_EQ(1u, returned_to_child.size());
1928 child_resource_provider->ReceiveReturnsFromParent(returned_to_child);
1931 // The child remembers the texture filter is set to |child_filter|.
1932 EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, child_texture_id));
1933 SetResourceFilter(child_resource_provider.get(), id, child_filter);
1934 Mock::VerifyAndClearExpectations(child_context);
1938 TEST_P(ResourceProviderTest, TextureFilters_ChildNearestParentLinear) {
1939 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
1940 return;
1941 ResourceProviderTestTextureFilters::RunTest(GL_NEAREST, GL_LINEAR);
1944 TEST_P(ResourceProviderTest, TextureFilters_ChildLinearParentNearest) {
1945 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
1946 return;
1947 ResourceProviderTestTextureFilters::RunTest(GL_LINEAR, GL_NEAREST);
1950 TEST_P(ResourceProviderTest, TransferMailboxResources) {
1951 // Other mailbox transfers tested elsewhere.
1952 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
1953 return;
1954 unsigned texture = context()->createTexture();
1955 context()->bindTexture(GL_TEXTURE_2D, texture);
1956 uint8_t data[4] = { 1, 2, 3, 4 };
1957 context()->texImage2D(
1958 GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &data);
1959 gpu::Mailbox mailbox;
1960 context()->genMailboxCHROMIUM(mailbox.name);
1961 context()->produceTextureDirectCHROMIUM(texture, GL_TEXTURE_2D, mailbox.name);
1962 uint32 sync_point = context()->insertSyncPoint();
1964 // All the logic below assumes that the sync points are all positive.
1965 EXPECT_LT(0u, sync_point);
1967 uint32 release_sync_point = 0;
1968 bool lost_resource = false;
1969 BlockingTaskRunner* main_thread_task_runner = NULL;
1970 ReleaseCallbackImpl callback = base::Bind(ReleaseCallback,
1971 &release_sync_point,
1972 &lost_resource,
1973 &main_thread_task_runner);
1974 ResourceId resource = resource_provider_->CreateResourceFromTextureMailbox(
1975 TextureMailbox(mailbox, GL_TEXTURE_2D, sync_point),
1976 SingleReleaseCallbackImpl::Create(callback));
1977 EXPECT_EQ(1u, context()->NumTextures());
1978 EXPECT_EQ(0u, release_sync_point);
1980 // Transfer the resource, expect the sync points to be consistent.
1981 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1982 resource_ids_to_transfer.push_back(resource);
1983 TransferableResourceArray list;
1984 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
1985 ASSERT_EQ(1u, list.size());
1986 EXPECT_LE(sync_point, list[0].mailbox_holder.sync_point);
1987 EXPECT_EQ(0,
1988 memcmp(mailbox.name,
1989 list[0].mailbox_holder.mailbox.name,
1990 sizeof(mailbox.name)));
1991 EXPECT_EQ(0u, release_sync_point);
1993 context()->waitSyncPoint(list[0].mailbox_holder.sync_point);
1994 unsigned other_texture =
1995 context()->createAndConsumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
1996 uint8_t test_data[4] = { 0 };
1997 context()->GetPixels(
1998 gfx::Size(1, 1), RGBA_8888, test_data);
1999 EXPECT_EQ(0, memcmp(data, test_data, sizeof(data)));
2001 context()->produceTextureDirectCHROMIUM(other_texture, GL_TEXTURE_2D,
2002 mailbox.name);
2003 context()->deleteTexture(other_texture);
2004 list[0].mailbox_holder.sync_point = context()->insertSyncPoint();
2005 EXPECT_LT(0u, list[0].mailbox_holder.sync_point);
2007 // Receive the resource, then delete it, expect the sync points to be
2008 // consistent.
2009 ReturnedResourceArray returned;
2010 TransferableResource::ReturnResources(list, &returned);
2011 resource_provider_->ReceiveReturnsFromParent(returned);
2012 EXPECT_EQ(1u, context()->NumTextures());
2013 EXPECT_EQ(0u, release_sync_point);
2015 resource_provider_->DeleteResource(resource);
2016 EXPECT_LE(list[0].mailbox_holder.sync_point, release_sync_point);
2017 EXPECT_FALSE(lost_resource);
2018 EXPECT_EQ(main_thread_task_runner_.get(), main_thread_task_runner);
2021 // We're going to do the same thing as above, but testing the case where we
2022 // delete the resource before we receive it back.
2023 sync_point = release_sync_point;
2024 EXPECT_LT(0u, sync_point);
2025 release_sync_point = 0;
2026 resource = resource_provider_->CreateResourceFromTextureMailbox(
2027 TextureMailbox(mailbox, GL_TEXTURE_2D, sync_point),
2028 SingleReleaseCallbackImpl::Create(callback));
2029 EXPECT_EQ(1u, context()->NumTextures());
2030 EXPECT_EQ(0u, release_sync_point);
2032 // Transfer the resource, expect the sync points to be consistent.
2033 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2034 resource_ids_to_transfer.push_back(resource);
2035 TransferableResourceArray list;
2036 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
2037 ASSERT_EQ(1u, list.size());
2038 EXPECT_LE(sync_point, list[0].mailbox_holder.sync_point);
2039 EXPECT_EQ(0,
2040 memcmp(mailbox.name,
2041 list[0].mailbox_holder.mailbox.name,
2042 sizeof(mailbox.name)));
2043 EXPECT_EQ(0u, release_sync_point);
2045 context()->waitSyncPoint(list[0].mailbox_holder.sync_point);
2046 unsigned other_texture =
2047 context()->createAndConsumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
2048 uint8_t test_data[4] = { 0 };
2049 context()->GetPixels(
2050 gfx::Size(1, 1), RGBA_8888, test_data);
2051 EXPECT_EQ(0, memcmp(data, test_data, sizeof(data)));
2053 context()->produceTextureDirectCHROMIUM(other_texture, GL_TEXTURE_2D,
2054 mailbox.name);
2055 context()->deleteTexture(other_texture);
2056 list[0].mailbox_holder.sync_point = context()->insertSyncPoint();
2057 EXPECT_LT(0u, list[0].mailbox_holder.sync_point);
2059 // Delete the resource, which shouldn't do anything.
2060 resource_provider_->DeleteResource(resource);
2061 EXPECT_EQ(1u, context()->NumTextures());
2062 EXPECT_EQ(0u, release_sync_point);
2064 // Then receive the resource which should release the mailbox, expect the
2065 // sync points to be consistent.
2066 ReturnedResourceArray returned;
2067 TransferableResource::ReturnResources(list, &returned);
2068 resource_provider_->ReceiveReturnsFromParent(returned);
2069 EXPECT_LE(list[0].mailbox_holder.sync_point, release_sync_point);
2070 EXPECT_FALSE(lost_resource);
2071 EXPECT_EQ(main_thread_task_runner_.get(), main_thread_task_runner);
2074 context()->waitSyncPoint(release_sync_point);
2075 texture =
2076 context()->createAndConsumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
2077 context()->deleteTexture(texture);
2080 TEST_P(ResourceProviderTest, LostResourceInParent) {
2081 gfx::Size size(1, 1);
2082 ResourceFormat format = RGBA_8888;
2083 ResourceId resource = child_resource_provider_->CreateResource(
2084 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
2085 child_resource_provider_->AllocateForTesting(resource);
2086 // Expect a GL resource to be lost.
2087 bool should_lose_resource =
2088 GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE;
2090 ReturnedResourceArray returned_to_child;
2091 int child_id =
2092 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
2094 // Transfer the resource to the parent.
2095 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2096 resource_ids_to_transfer.push_back(resource);
2097 TransferableResourceArray list;
2098 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
2099 &list);
2100 EXPECT_EQ(1u, list.size());
2102 resource_provider_->ReceiveFromChild(child_id, list);
2103 ResourceProvider::ResourceIdSet resource_ids_to_receive;
2104 resource_ids_to_receive.insert(resource);
2105 resource_provider_->DeclareUsedResourcesFromChild(child_id,
2106 resource_ids_to_receive);
2109 // Lose the output surface in the parent.
2110 resource_provider_->DidLoseOutputSurface();
2113 EXPECT_EQ(0u, returned_to_child.size());
2115 // Transfer resources back from the parent to the child. Set no resources as
2116 // being in use.
2117 ResourceProvider::ResourceIdSet no_resources;
2118 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
2120 // Expect a GL resource to be lost.
2121 ASSERT_EQ(1u, returned_to_child.size());
2122 EXPECT_EQ(should_lose_resource, returned_to_child[0].lost);
2123 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
2124 returned_to_child.clear();
2127 // A GL resource should be lost.
2128 EXPECT_EQ(should_lose_resource, child_resource_provider_->IsLost(resource));
2130 // Lost resources stay in use in the parent forever.
2131 EXPECT_EQ(should_lose_resource,
2132 child_resource_provider_->InUseByConsumer(resource));
2135 TEST_P(ResourceProviderTest, LostResourceInGrandParent) {
2136 gfx::Size size(1, 1);
2137 ResourceFormat format = RGBA_8888;
2138 ResourceId resource = child_resource_provider_->CreateResource(
2139 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
2140 child_resource_provider_->AllocateForTesting(resource);
2142 ReturnedResourceArray returned_to_child;
2143 int child_id =
2144 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
2146 // Transfer the resource to the parent.
2147 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2148 resource_ids_to_transfer.push_back(resource);
2149 TransferableResourceArray list;
2150 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
2151 &list);
2152 EXPECT_EQ(1u, list.size());
2154 resource_provider_->ReceiveFromChild(child_id, list);
2155 ResourceProvider::ResourceIdSet resource_ids_to_receive;
2156 resource_ids_to_receive.insert(resource);
2157 resource_provider_->DeclareUsedResourcesFromChild(child_id,
2158 resource_ids_to_receive);
2162 ResourceProvider::ResourceIdMap resource_map =
2163 resource_provider_->GetChildToParentMap(child_id);
2164 ResourceId parent_resource = resource_map[resource];
2165 EXPECT_NE(0u, parent_resource);
2167 // Transfer to a grandparent.
2168 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2169 resource_ids_to_transfer.push_back(parent_resource);
2170 TransferableResourceArray list;
2171 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
2173 // Receive back a lost resource from the grandparent.
2174 EXPECT_EQ(1u, list.size());
2175 EXPECT_EQ(parent_resource, list[0].id);
2176 ReturnedResourceArray returned;
2177 TransferableResource::ReturnResources(list, &returned);
2178 EXPECT_EQ(1u, returned.size());
2179 EXPECT_EQ(parent_resource, returned[0].id);
2180 returned[0].lost = true;
2181 resource_provider_->ReceiveReturnsFromParent(returned);
2183 // The resource should be lost.
2184 EXPECT_TRUE(resource_provider_->IsLost(parent_resource));
2186 // Lost resources stay in use in the parent forever.
2187 EXPECT_TRUE(resource_provider_->InUseByConsumer(parent_resource));
2191 EXPECT_EQ(0u, returned_to_child.size());
2193 // Transfer resources back from the parent to the child. Set no resources as
2194 // being in use.
2195 ResourceProvider::ResourceIdSet no_resources;
2196 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
2198 // Expect the resource to be lost.
2199 ASSERT_EQ(1u, returned_to_child.size());
2200 EXPECT_TRUE(returned_to_child[0].lost);
2201 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
2202 returned_to_child.clear();
2205 // The resource should be lost.
2206 EXPECT_TRUE(child_resource_provider_->IsLost(resource));
2208 // Lost resources stay in use in the parent forever.
2209 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(resource));
2212 TEST_P(ResourceProviderTest, LostMailboxInParent) {
2213 uint32 release_sync_point = 0;
2214 bool lost_resource = false;
2215 bool release_called = false;
2216 uint32 sync_point = 0;
2217 ResourceId resource = CreateChildMailbox(&release_sync_point, &lost_resource,
2218 &release_called, &sync_point);
2220 ReturnedResourceArray returned_to_child;
2221 int child_id =
2222 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
2224 // Transfer the resource to the parent.
2225 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2226 resource_ids_to_transfer.push_back(resource);
2227 TransferableResourceArray list;
2228 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
2229 &list);
2230 EXPECT_EQ(1u, list.size());
2232 resource_provider_->ReceiveFromChild(child_id, list);
2233 ResourceProvider::ResourceIdSet resource_ids_to_receive;
2234 resource_ids_to_receive.insert(resource);
2235 resource_provider_->DeclareUsedResourcesFromChild(child_id,
2236 resource_ids_to_receive);
2239 // Lose the output surface in the parent.
2240 resource_provider_->DidLoseOutputSurface();
2243 EXPECT_EQ(0u, returned_to_child.size());
2245 // Transfer resources back from the parent to the child. Set no resources as
2246 // being in use.
2247 ResourceProvider::ResourceIdSet no_resources;
2248 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
2250 ASSERT_EQ(1u, returned_to_child.size());
2251 // Losing an output surface only loses hardware resources.
2252 EXPECT_EQ(returned_to_child[0].lost,
2253 GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE);
2254 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
2255 returned_to_child.clear();
2258 // Delete the resource in the child. Expect the resource to be lost if it's
2259 // a GL texture.
2260 child_resource_provider_->DeleteResource(resource);
2261 EXPECT_EQ(lost_resource,
2262 GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE);
2265 TEST_P(ResourceProviderTest, LostMailboxInGrandParent) {
2266 uint32 release_sync_point = 0;
2267 bool lost_resource = false;
2268 bool release_called = false;
2269 uint32 sync_point = 0;
2270 ResourceId resource = CreateChildMailbox(&release_sync_point, &lost_resource,
2271 &release_called, &sync_point);
2273 ReturnedResourceArray returned_to_child;
2274 int child_id =
2275 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
2277 // Transfer the resource to the parent.
2278 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2279 resource_ids_to_transfer.push_back(resource);
2280 TransferableResourceArray list;
2281 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
2282 &list);
2283 EXPECT_EQ(1u, list.size());
2285 resource_provider_->ReceiveFromChild(child_id, list);
2286 ResourceProvider::ResourceIdSet resource_ids_to_receive;
2287 resource_ids_to_receive.insert(resource);
2288 resource_provider_->DeclareUsedResourcesFromChild(child_id,
2289 resource_ids_to_receive);
2293 ResourceProvider::ResourceIdMap resource_map =
2294 resource_provider_->GetChildToParentMap(child_id);
2295 ResourceId parent_resource = resource_map[resource];
2296 EXPECT_NE(0u, parent_resource);
2298 // Transfer to a grandparent.
2299 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2300 resource_ids_to_transfer.push_back(parent_resource);
2301 TransferableResourceArray list;
2302 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
2304 // Receive back a lost resource from the grandparent.
2305 EXPECT_EQ(1u, list.size());
2306 EXPECT_EQ(parent_resource, list[0].id);
2307 ReturnedResourceArray returned;
2308 TransferableResource::ReturnResources(list, &returned);
2309 EXPECT_EQ(1u, returned.size());
2310 EXPECT_EQ(parent_resource, returned[0].id);
2311 returned[0].lost = true;
2312 resource_provider_->ReceiveReturnsFromParent(returned);
2316 EXPECT_EQ(0u, returned_to_child.size());
2318 // Transfer resources back from the parent to the child. Set no resources as
2319 // being in use.
2320 ResourceProvider::ResourceIdSet no_resources;
2321 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
2323 // Expect the resource to be lost.
2324 ASSERT_EQ(1u, returned_to_child.size());
2325 EXPECT_TRUE(returned_to_child[0].lost);
2326 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
2327 returned_to_child.clear();
2330 // Delete the resource in the child. Expect the resource to be lost.
2331 child_resource_provider_->DeleteResource(resource);
2332 EXPECT_TRUE(lost_resource);
2335 TEST_P(ResourceProviderTest, Shutdown) {
2336 uint32 release_sync_point = 0;
2337 bool lost_resource = false;
2338 bool release_called = false;
2339 uint32 sync_point = 0;
2340 CreateChildMailbox(
2341 &release_sync_point, &lost_resource, &release_called, &sync_point);
2343 EXPECT_EQ(0u, release_sync_point);
2344 EXPECT_FALSE(lost_resource);
2346 child_resource_provider_ = nullptr;
2348 if (GetParam() == ResourceProvider::RESOURCE_TYPE_GL_TEXTURE) {
2349 EXPECT_LE(sync_point, release_sync_point);
2351 EXPECT_TRUE(release_called);
2352 EXPECT_FALSE(lost_resource);
2355 TEST_P(ResourceProviderTest, ShutdownWithExportedResource) {
2356 uint32 release_sync_point = 0;
2357 bool lost_resource = false;
2358 bool release_called = false;
2359 uint32 sync_point = 0;
2360 ResourceId resource = CreateChildMailbox(&release_sync_point, &lost_resource,
2361 &release_called, &sync_point);
2363 // Transfer the resource, so we can't release it properly on shutdown.
2364 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2365 resource_ids_to_transfer.push_back(resource);
2366 TransferableResourceArray list;
2367 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
2368 &list);
2370 EXPECT_EQ(0u, release_sync_point);
2371 EXPECT_FALSE(lost_resource);
2373 child_resource_provider_ = nullptr;
2375 // Since the resource is in the parent, the child considers it lost.
2376 EXPECT_EQ(0u, release_sync_point);
2377 EXPECT_TRUE(lost_resource);
2380 TEST_P(ResourceProviderTest, LostContext) {
2381 // TextureMailbox callbacks only exist for GL textures for now.
2382 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
2383 return;
2384 unsigned texture = context()->createTexture();
2385 context()->bindTexture(GL_TEXTURE_2D, texture);
2386 gpu::Mailbox mailbox;
2387 context()->genMailboxCHROMIUM(mailbox.name);
2388 context()->produceTextureDirectCHROMIUM(texture, GL_TEXTURE_2D, mailbox.name);
2389 uint32 sync_point = context()->insertSyncPoint();
2391 EXPECT_LT(0u, sync_point);
2393 uint32 release_sync_point = 0;
2394 bool lost_resource = false;
2395 BlockingTaskRunner* main_thread_task_runner = NULL;
2396 scoped_ptr<SingleReleaseCallbackImpl> callback =
2397 SingleReleaseCallbackImpl::Create(base::Bind(ReleaseCallback,
2398 &release_sync_point,
2399 &lost_resource,
2400 &main_thread_task_runner));
2401 resource_provider_->CreateResourceFromTextureMailbox(
2402 TextureMailbox(mailbox, GL_TEXTURE_2D, sync_point), callback.Pass());
2404 EXPECT_EQ(0u, release_sync_point);
2405 EXPECT_FALSE(lost_resource);
2406 EXPECT_EQ(NULL, main_thread_task_runner);
2408 resource_provider_->DidLoseOutputSurface();
2409 resource_provider_ = nullptr;
2411 EXPECT_LE(sync_point, release_sync_point);
2412 EXPECT_TRUE(lost_resource);
2413 EXPECT_EQ(main_thread_task_runner_.get(), main_thread_task_runner);
2416 TEST_P(ResourceProviderTest, ScopedSampler) {
2417 // Sampling is only supported for GL textures.
2418 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
2419 return;
2421 scoped_ptr<TextureStateTrackingContext> context_owned(
2422 new TextureStateTrackingContext);
2423 TextureStateTrackingContext* context = context_owned.get();
2425 FakeOutputSurfaceClient output_surface_client;
2426 scoped_ptr<OutputSurface> output_surface(
2427 FakeOutputSurface::Create3d(context_owned.Pass()));
2428 CHECK(output_surface->BindToClient(&output_surface_client));
2430 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
2431 output_surface.get(), shared_bitmap_manager_.get(),
2432 gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false));
2434 gfx::Size size(1, 1);
2435 ResourceFormat format = RGBA_8888;
2436 int texture_id = 1;
2438 ResourceId id = resource_provider->CreateResource(
2439 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
2441 // Check that the texture gets created with the right sampler settings.
2442 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id))
2443 .Times(2); // Once to create and once to allocate.
2444 EXPECT_CALL(*context,
2445 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
2446 EXPECT_CALL(*context,
2447 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
2448 EXPECT_CALL(
2449 *context,
2450 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
2451 EXPECT_CALL(
2452 *context,
2453 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
2454 EXPECT_CALL(*context,
2455 texParameteri(GL_TEXTURE_2D,
2456 GL_TEXTURE_POOL_CHROMIUM,
2457 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM));
2459 resource_provider->AllocateForTesting(id);
2460 Mock::VerifyAndClearExpectations(context);
2462 // Creating a sampler with the default filter should not change any texture
2463 // parameters.
2465 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
2466 ResourceProvider::ScopedSamplerGL sampler(
2467 resource_provider.get(), id, GL_TEXTURE_2D, GL_LINEAR);
2468 Mock::VerifyAndClearExpectations(context);
2471 // Using a different filter should be reflected in the texture parameters.
2473 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
2474 EXPECT_CALL(
2475 *context,
2476 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
2477 EXPECT_CALL(
2478 *context,
2479 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
2480 ResourceProvider::ScopedSamplerGL sampler(
2481 resource_provider.get(), id, GL_TEXTURE_2D, GL_NEAREST);
2482 Mock::VerifyAndClearExpectations(context);
2485 // Test resetting to the default filter.
2487 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
2488 EXPECT_CALL(*context,
2489 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
2490 EXPECT_CALL(*context,
2491 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
2492 ResourceProvider::ScopedSamplerGL sampler(
2493 resource_provider.get(), id, GL_TEXTURE_2D, GL_LINEAR);
2494 Mock::VerifyAndClearExpectations(context);
2498 TEST_P(ResourceProviderTest, ManagedResource) {
2499 // Sampling is only supported for GL textures.
2500 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
2501 return;
2503 scoped_ptr<TextureStateTrackingContext> context_owned(
2504 new TextureStateTrackingContext);
2505 TextureStateTrackingContext* context = context_owned.get();
2507 FakeOutputSurfaceClient output_surface_client;
2508 scoped_ptr<OutputSurface> output_surface(
2509 FakeOutputSurface::Create3d(context_owned.Pass()));
2510 CHECK(output_surface->BindToClient(&output_surface_client));
2512 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
2513 output_surface.get(), shared_bitmap_manager_.get(),
2514 gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false));
2516 gfx::Size size(1, 1);
2517 ResourceFormat format = RGBA_8888;
2518 int texture_id = 1;
2520 // Check that the texture gets created with the right sampler settings.
2521 ResourceId id = resource_provider->CreateManagedResource(
2522 size, GL_TEXTURE_2D, GL_CLAMP_TO_EDGE,
2523 ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
2524 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
2525 EXPECT_CALL(*context,
2526 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
2527 EXPECT_CALL(*context,
2528 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
2529 EXPECT_CALL(
2530 *context,
2531 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
2532 EXPECT_CALL(
2533 *context,
2534 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
2535 EXPECT_CALL(*context,
2536 texParameteri(GL_TEXTURE_2D,
2537 GL_TEXTURE_POOL_CHROMIUM,
2538 GL_TEXTURE_POOL_MANAGED_CHROMIUM));
2539 resource_provider->CreateForTesting(id);
2540 EXPECT_NE(0u, id);
2542 Mock::VerifyAndClearExpectations(context);
2545 TEST_P(ResourceProviderTest, TextureWrapMode) {
2546 // Sampling is only supported for GL textures.
2547 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
2548 return;
2550 scoped_ptr<TextureStateTrackingContext> context_owned(
2551 new TextureStateTrackingContext);
2552 TextureStateTrackingContext* context = context_owned.get();
2554 FakeOutputSurfaceClient output_surface_client;
2555 scoped_ptr<OutputSurface> output_surface(
2556 FakeOutputSurface::Create3d(context_owned.Pass()));
2557 CHECK(output_surface->BindToClient(&output_surface_client));
2559 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
2560 output_surface.get(), shared_bitmap_manager_.get(),
2561 gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false));
2563 gfx::Size size(1, 1);
2564 ResourceFormat format = RGBA_8888;
2565 GLenum texture_pool = GL_TEXTURE_POOL_UNMANAGED_CHROMIUM;
2567 for (int texture_id = 1; texture_id <= 2; ++texture_id) {
2568 GLint wrap_mode = texture_id == 1 ? GL_CLAMP_TO_EDGE : GL_REPEAT;
2569 // Check that the texture gets created with the right sampler settings.
2570 ResourceId id = resource_provider->CreateGLTexture(
2571 size, GL_TEXTURE_2D, texture_pool, wrap_mode,
2572 ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
2573 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
2574 EXPECT_CALL(*context,
2575 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
2576 EXPECT_CALL(*context,
2577 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
2578 EXPECT_CALL(*context,
2579 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap_mode));
2580 EXPECT_CALL(*context,
2581 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap_mode));
2582 EXPECT_CALL(*context,
2583 texParameteri(GL_TEXTURE_2D,
2584 GL_TEXTURE_POOL_CHROMIUM,
2585 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM));
2586 resource_provider->CreateForTesting(id);
2587 EXPECT_NE(0u, id);
2589 Mock::VerifyAndClearExpectations(context);
2593 TEST_P(ResourceProviderTest, TextureHint) {
2594 // Sampling is only supported for GL textures.
2595 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
2596 return;
2598 scoped_ptr<TextureStateTrackingContext> context_owned(
2599 new TextureStateTrackingContext);
2600 TextureStateTrackingContext* context = context_owned.get();
2601 context->set_support_texture_storage(true);
2602 context->set_support_texture_usage(true);
2604 FakeOutputSurfaceClient output_surface_client;
2605 scoped_ptr<OutputSurface> output_surface(
2606 FakeOutputSurface::Create3d(context_owned.Pass()));
2607 CHECK(output_surface->BindToClient(&output_surface_client));
2609 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
2610 output_surface.get(), shared_bitmap_manager_.get(),
2611 gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false));
2613 gfx::Size size(1, 1);
2614 ResourceFormat format = RGBA_8888;
2615 GLenum texture_pool = GL_TEXTURE_POOL_UNMANAGED_CHROMIUM;
2617 const ResourceProvider::TextureHint hints[4] = {
2618 ResourceProvider::TEXTURE_HINT_DEFAULT,
2619 ResourceProvider::TEXTURE_HINT_IMMUTABLE,
2620 ResourceProvider::TEXTURE_HINT_FRAMEBUFFER,
2621 ResourceProvider::TEXTURE_HINT_IMMUTABLE_FRAMEBUFFER,
2623 for (GLuint texture_id = 1; texture_id <= arraysize(hints); ++texture_id) {
2624 // Check that the texture gets created with the right sampler settings.
2625 ResourceId id = resource_provider->CreateGLTexture(
2626 size, GL_TEXTURE_2D, texture_pool, GL_CLAMP_TO_EDGE,
2627 hints[texture_id - 1], format);
2628 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
2629 EXPECT_CALL(*context,
2630 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
2631 EXPECT_CALL(*context,
2632 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
2633 EXPECT_CALL(
2634 *context,
2635 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
2636 EXPECT_CALL(
2637 *context,
2638 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
2639 EXPECT_CALL(*context,
2640 texParameteri(GL_TEXTURE_2D,
2641 GL_TEXTURE_POOL_CHROMIUM,
2642 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM));
2643 // Check only TEXTURE_HINT_FRAMEBUFFER set GL_TEXTURE_USAGE_ANGLE.
2644 bool is_framebuffer_hint =
2645 hints[texture_id - 1] & ResourceProvider::TEXTURE_HINT_FRAMEBUFFER;
2646 EXPECT_CALL(*context,
2647 texParameteri(GL_TEXTURE_2D,
2648 GL_TEXTURE_USAGE_ANGLE,
2649 GL_FRAMEBUFFER_ATTACHMENT_ANGLE))
2650 .Times(is_framebuffer_hint ? 1 : 0);
2651 resource_provider->CreateForTesting(id);
2652 EXPECT_NE(0u, id);
2654 Mock::VerifyAndClearExpectations(context);
2658 TEST_P(ResourceProviderTest, TextureMailbox_SharedMemory) {
2659 if (GetParam() != ResourceProvider::RESOURCE_TYPE_BITMAP)
2660 return;
2662 gfx::Size size(64, 64);
2663 const uint32_t kBadBeef = 0xbadbeef;
2664 scoped_ptr<SharedBitmap> shared_bitmap(
2665 CreateAndFillSharedBitmap(shared_bitmap_manager_.get(), size, kBadBeef));
2667 FakeOutputSurfaceClient output_surface_client;
2668 scoped_ptr<OutputSurface> output_surface(
2669 FakeOutputSurface::CreateSoftware(make_scoped_ptr(
2670 new SoftwareOutputDevice)));
2671 CHECK(output_surface->BindToClient(&output_surface_client));
2673 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
2674 output_surface.get(), shared_bitmap_manager_.get(),
2675 gpu_memory_buffer_manager_.get(), main_thread_task_runner_.get(), 0,
2676 false, 1, false));
2678 uint32 release_sync_point = 0;
2679 bool lost_resource = false;
2680 BlockingTaskRunner* main_thread_task_runner = NULL;
2681 scoped_ptr<SingleReleaseCallbackImpl> callback =
2682 SingleReleaseCallbackImpl::Create(base::Bind(&ReleaseCallback,
2683 &release_sync_point,
2684 &lost_resource,
2685 &main_thread_task_runner));
2686 TextureMailbox mailbox(shared_bitmap.get(), size);
2688 ResourceId id = resource_provider->CreateResourceFromTextureMailbox(
2689 mailbox, callback.Pass());
2690 EXPECT_NE(0u, id);
2693 ResourceProvider::ScopedReadLockSoftware lock(resource_provider.get(), id);
2694 const SkBitmap* sk_bitmap = lock.sk_bitmap();
2695 EXPECT_EQ(sk_bitmap->width(), size.width());
2696 EXPECT_EQ(sk_bitmap->height(), size.height());
2697 EXPECT_EQ(*sk_bitmap->getAddr32(16, 16), kBadBeef);
2700 resource_provider->DeleteResource(id);
2701 EXPECT_EQ(0u, release_sync_point);
2702 EXPECT_FALSE(lost_resource);
2703 EXPECT_EQ(main_thread_task_runner_.get(), main_thread_task_runner);
2706 class ResourceProviderTestTextureMailboxGLFilters
2707 : public ResourceProviderTest {
2708 public:
2709 static void RunTest(TestSharedBitmapManager* shared_bitmap_manager,
2710 TestGpuMemoryBufferManager* gpu_memory_buffer_manager,
2711 BlockingTaskRunner* main_thread_task_runner,
2712 bool mailbox_nearest_neighbor,
2713 GLenum sampler_filter) {
2714 scoped_ptr<TextureStateTrackingContext> context_owned(
2715 new TextureStateTrackingContext);
2716 TextureStateTrackingContext* context = context_owned.get();
2718 FakeOutputSurfaceClient output_surface_client;
2719 scoped_ptr<OutputSurface> output_surface(
2720 FakeOutputSurface::Create3d(context_owned.Pass()));
2721 CHECK(output_surface->BindToClient(&output_surface_client));
2723 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
2724 output_surface.get(), shared_bitmap_manager, gpu_memory_buffer_manager,
2725 main_thread_task_runner, 0, false, 1, false));
2727 unsigned texture_id = 1;
2728 uint32 sync_point = 30;
2729 unsigned target = GL_TEXTURE_2D;
2731 EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
2732 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
2733 EXPECT_CALL(*context, insertSyncPoint()).Times(0);
2734 EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _, _)).Times(0);
2735 EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(_, _)).Times(0);
2737 gpu::Mailbox gpu_mailbox;
2738 memcpy(gpu_mailbox.name, "Hello world", strlen("Hello world") + 1);
2739 uint32 release_sync_point = 0;
2740 bool lost_resource = false;
2741 BlockingTaskRunner* mailbox_task_runner = NULL;
2742 scoped_ptr<SingleReleaseCallbackImpl> callback =
2743 SingleReleaseCallbackImpl::Create(base::Bind(&ReleaseCallback,
2744 &release_sync_point,
2745 &lost_resource,
2746 &mailbox_task_runner));
2748 TextureMailbox mailbox(gpu_mailbox, target, sync_point);
2749 mailbox.set_nearest_neighbor(mailbox_nearest_neighbor);
2751 ResourceId id = resource_provider->CreateResourceFromTextureMailbox(
2752 mailbox, callback.Pass());
2753 EXPECT_NE(0u, id);
2755 Mock::VerifyAndClearExpectations(context);
2758 // Mailbox sync point WaitSyncPoint before using the texture.
2759 EXPECT_CALL(*context, waitSyncPoint(sync_point));
2760 resource_provider->WaitSyncPointIfNeeded(id);
2761 Mock::VerifyAndClearExpectations(context);
2763 EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(target, _))
2764 .WillOnce(Return(texture_id));
2765 EXPECT_CALL(*context, bindTexture(target, texture_id));
2767 EXPECT_CALL(*context, insertSyncPoint()).Times(0);
2768 EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _, _)).Times(0);
2770 // The sampler will reset these if |mailbox_nearest_neighbor| does not
2771 // match |sampler_filter|.
2772 if (mailbox_nearest_neighbor != (sampler_filter == GL_NEAREST)) {
2773 EXPECT_CALL(*context, texParameteri(
2774 GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, sampler_filter));
2775 EXPECT_CALL(*context, texParameteri(
2776 GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, sampler_filter));
2779 ResourceProvider::ScopedSamplerGL lock(
2780 resource_provider.get(), id, sampler_filter);
2781 Mock::VerifyAndClearExpectations(context);
2783 // When done with it, a sync point should be inserted, but no produce is
2784 // necessary.
2785 EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
2786 EXPECT_CALL(*context, insertSyncPoint());
2787 EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _, _)).Times(0);
2789 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
2790 EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(_, _)).Times(0);
2793 resource_provider->DeleteResource(id);
2794 EXPECT_EQ(0u, release_sync_point);
2795 EXPECT_FALSE(lost_resource);
2796 EXPECT_EQ(main_thread_task_runner, mailbox_task_runner);
2800 TEST_P(ResourceProviderTest, TextureMailbox_GLTexture2D_LinearToLinear) {
2801 // Mailboxing is only supported for GL textures.
2802 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
2803 return;
2805 ResourceProviderTestTextureMailboxGLFilters::RunTest(
2806 shared_bitmap_manager_.get(),
2807 gpu_memory_buffer_manager_.get(),
2808 main_thread_task_runner_.get(),
2809 false,
2810 GL_LINEAR);
2813 TEST_P(ResourceProviderTest, TextureMailbox_GLTexture2D_NearestToNearest) {
2814 // Mailboxing is only supported for GL textures.
2815 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
2816 return;
2818 ResourceProviderTestTextureMailboxGLFilters::RunTest(
2819 shared_bitmap_manager_.get(),
2820 gpu_memory_buffer_manager_.get(),
2821 main_thread_task_runner_.get(),
2822 true,
2823 GL_NEAREST);
2826 TEST_P(ResourceProviderTest, TextureMailbox_GLTexture2D_NearestToLinear) {
2827 // Mailboxing is only supported for GL textures.
2828 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
2829 return;
2831 ResourceProviderTestTextureMailboxGLFilters::RunTest(
2832 shared_bitmap_manager_.get(),
2833 gpu_memory_buffer_manager_.get(),
2834 main_thread_task_runner_.get(),
2835 true,
2836 GL_LINEAR);
2839 TEST_P(ResourceProviderTest, TextureMailbox_GLTexture2D_LinearToNearest) {
2840 // Mailboxing is only supported for GL textures.
2841 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
2842 return;
2844 ResourceProviderTestTextureMailboxGLFilters::RunTest(
2845 shared_bitmap_manager_.get(),
2846 gpu_memory_buffer_manager_.get(),
2847 main_thread_task_runner_.get(),
2848 false,
2849 GL_NEAREST);
2852 TEST_P(ResourceProviderTest, TextureMailbox_GLTextureExternalOES) {
2853 // Mailboxing is only supported for GL textures.
2854 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
2855 return;
2857 scoped_ptr<TextureStateTrackingContext> context_owned(
2858 new TextureStateTrackingContext);
2859 TextureStateTrackingContext* context = context_owned.get();
2861 FakeOutputSurfaceClient output_surface_client;
2862 scoped_ptr<OutputSurface> output_surface(
2863 FakeOutputSurface::Create3d(context_owned.Pass()));
2864 CHECK(output_surface->BindToClient(&output_surface_client));
2866 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
2867 output_surface.get(), shared_bitmap_manager_.get(),
2868 gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false));
2870 uint32 sync_point = 30;
2871 unsigned target = GL_TEXTURE_EXTERNAL_OES;
2873 EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
2874 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
2875 EXPECT_CALL(*context, insertSyncPoint()).Times(0);
2876 EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _, _)).Times(0);
2877 EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(_, _)).Times(0);
2879 gpu::Mailbox gpu_mailbox;
2880 memcpy(gpu_mailbox.name, "Hello world", strlen("Hello world") + 1);
2881 scoped_ptr<SingleReleaseCallbackImpl> callback =
2882 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback));
2884 TextureMailbox mailbox(gpu_mailbox, target, sync_point);
2886 ResourceId id = resource_provider->CreateResourceFromTextureMailbox(
2887 mailbox, callback.Pass());
2888 EXPECT_NE(0u, id);
2890 Mock::VerifyAndClearExpectations(context);
2893 // Mailbox sync point WaitSyncPoint before using the texture.
2894 EXPECT_CALL(*context, waitSyncPoint(sync_point));
2895 resource_provider->WaitSyncPointIfNeeded(id);
2896 Mock::VerifyAndClearExpectations(context);
2898 unsigned texture_id = 1;
2900 EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(target, _))
2901 .WillOnce(Return(texture_id));
2903 EXPECT_CALL(*context, insertSyncPoint()).Times(0);
2904 EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _, _)).Times(0);
2906 ResourceProvider::ScopedReadLockGL lock(resource_provider.get(), id);
2907 Mock::VerifyAndClearExpectations(context);
2909 // When done with it, a sync point should be inserted, but no produce is
2910 // necessary.
2911 EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
2912 EXPECT_CALL(*context, insertSyncPoint());
2913 EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _, _)).Times(0);
2915 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
2916 EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(_, _)).Times(0);
2920 TEST_P(ResourceProviderTest,
2921 TextureMailbox_WaitSyncPointIfNeeded_WithSyncPoint) {
2922 // Mailboxing is only supported for GL textures.
2923 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
2924 return;
2926 scoped_ptr<TextureStateTrackingContext> context_owned(
2927 new TextureStateTrackingContext);
2928 TextureStateTrackingContext* context = context_owned.get();
2930 FakeOutputSurfaceClient output_surface_client;
2931 scoped_ptr<OutputSurface> output_surface(
2932 FakeOutputSurface::Create3d(context_owned.Pass()));
2933 CHECK(output_surface->BindToClient(&output_surface_client));
2935 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
2936 output_surface.get(), shared_bitmap_manager_.get(),
2937 gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false));
2939 uint32 sync_point = 30;
2940 unsigned target = GL_TEXTURE_2D;
2942 EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
2943 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
2944 EXPECT_CALL(*context, insertSyncPoint()).Times(0);
2945 EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _, _)).Times(0);
2946 EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(_, _)).Times(0);
2948 gpu::Mailbox gpu_mailbox;
2949 memcpy(gpu_mailbox.name, "Hello world", strlen("Hello world") + 1);
2950 scoped_ptr<SingleReleaseCallbackImpl> callback =
2951 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback));
2953 TextureMailbox mailbox(gpu_mailbox, target, sync_point);
2955 ResourceId id = resource_provider->CreateResourceFromTextureMailbox(
2956 mailbox, callback.Pass());
2957 EXPECT_NE(0u, id);
2959 Mock::VerifyAndClearExpectations(context);
2962 // First call to WaitSyncPointIfNeeded should call waitSyncPoint.
2963 EXPECT_CALL(*context, waitSyncPoint(sync_point));
2964 resource_provider->WaitSyncPointIfNeeded(id);
2965 Mock::VerifyAndClearExpectations(context);
2967 // Subsequent calls to WaitSyncPointIfNeeded shouldn't call waitSyncPoint.
2968 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
2969 resource_provider->WaitSyncPointIfNeeded(id);
2970 Mock::VerifyAndClearExpectations(context);
2974 TEST_P(ResourceProviderTest, TextureMailbox_WaitSyncPointIfNeeded_NoSyncPoint) {
2975 // Mailboxing is only supported for GL textures.
2976 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
2977 return;
2979 scoped_ptr<TextureStateTrackingContext> context_owned(
2980 new TextureStateTrackingContext);
2981 TextureStateTrackingContext* context = context_owned.get();
2983 FakeOutputSurfaceClient output_surface_client;
2984 scoped_ptr<OutputSurface> output_surface(
2985 FakeOutputSurface::Create3d(context_owned.Pass()));
2986 CHECK(output_surface->BindToClient(&output_surface_client));
2988 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
2989 output_surface.get(), shared_bitmap_manager_.get(),
2990 gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false));
2992 uint32 sync_point = 0;
2993 unsigned target = GL_TEXTURE_2D;
2995 EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
2996 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
2997 EXPECT_CALL(*context, insertSyncPoint()).Times(0);
2998 EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _, _)).Times(0);
2999 EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(_, _)).Times(0);
3001 gpu::Mailbox gpu_mailbox;
3002 memcpy(gpu_mailbox.name, "Hello world", strlen("Hello world") + 1);
3003 scoped_ptr<SingleReleaseCallbackImpl> callback =
3004 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback));
3006 TextureMailbox mailbox(gpu_mailbox, target, sync_point);
3008 ResourceId id = resource_provider->CreateResourceFromTextureMailbox(
3009 mailbox, callback.Pass());
3010 EXPECT_NE(0u, id);
3012 Mock::VerifyAndClearExpectations(context);
3015 // WaitSyncPointIfNeeded with sync_point == 0 shouldn't call waitSyncPoint.
3016 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
3017 resource_provider->WaitSyncPointIfNeeded(id);
3018 Mock::VerifyAndClearExpectations(context);
3022 class AllocationTrackingContext3D : public TestWebGraphicsContext3D {
3023 public:
3024 MOCK_METHOD0(NextTextureId, GLuint());
3025 MOCK_METHOD1(RetireTextureId, void(GLuint id));
3026 MOCK_METHOD2(bindTexture, void(GLenum target, GLuint texture));
3027 MOCK_METHOD5(texStorage2DEXT,
3028 void(GLenum target,
3029 GLint levels,
3030 GLuint internalformat,
3031 GLint width,
3032 GLint height));
3033 MOCK_METHOD9(texImage2D,
3034 void(GLenum target,
3035 GLint level,
3036 GLenum internalformat,
3037 GLsizei width,
3038 GLsizei height,
3039 GLint border,
3040 GLenum format,
3041 GLenum type,
3042 const void* pixels));
3043 MOCK_METHOD9(texSubImage2D,
3044 void(GLenum target,
3045 GLint level,
3046 GLint xoffset,
3047 GLint yoffset,
3048 GLsizei width,
3049 GLsizei height,
3050 GLenum format,
3051 GLenum type,
3052 const void* pixels));
3053 MOCK_METHOD9(asyncTexImage2DCHROMIUM,
3054 void(GLenum target,
3055 GLint level,
3056 GLenum internalformat,
3057 GLsizei width,
3058 GLsizei height,
3059 GLint border,
3060 GLenum format,
3061 GLenum type,
3062 const void* pixels));
3063 MOCK_METHOD9(asyncTexSubImage2DCHROMIUM,
3064 void(GLenum target,
3065 GLint level,
3066 GLint xoffset,
3067 GLint yoffset,
3068 GLsizei width,
3069 GLsizei height,
3070 GLenum format,
3071 GLenum type,
3072 const void* pixels));
3073 MOCK_METHOD8(compressedTexImage2D,
3074 void(GLenum target,
3075 GLint level,
3076 GLenum internalformat,
3077 GLsizei width,
3078 GLsizei height,
3079 GLint border,
3080 GLsizei image_size,
3081 const void* data));
3082 MOCK_METHOD1(waitAsyncTexImage2DCHROMIUM, void(GLenum));
3083 MOCK_METHOD4(createImageCHROMIUM,
3084 GLuint(ClientBuffer, GLsizei, GLsizei, GLenum));
3085 MOCK_METHOD1(destroyImageCHROMIUM, void(GLuint));
3086 MOCK_METHOD2(bindTexImage2DCHROMIUM, void(GLenum, GLint));
3087 MOCK_METHOD2(releaseTexImage2DCHROMIUM, void(GLenum, GLint));
3089 // We're mocking bindTexture, so we override
3090 // TestWebGraphicsContext3D::texParameteri to avoid assertions related to the
3091 // currently bound texture.
3092 virtual void texParameteri(GLenum target, GLenum pname, GLint param) {}
3095 TEST_P(ResourceProviderTest, TextureAllocation) {
3096 // Only for GL textures.
3097 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
3098 return;
3099 scoped_ptr<AllocationTrackingContext3D> context_owned(
3100 new StrictMock<AllocationTrackingContext3D>);
3101 AllocationTrackingContext3D* context = context_owned.get();
3103 FakeOutputSurfaceClient output_surface_client;
3104 scoped_ptr<OutputSurface> output_surface(
3105 FakeOutputSurface::Create3d(context_owned.Pass()));
3106 CHECK(output_surface->BindToClient(&output_surface_client));
3108 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
3109 output_surface.get(), shared_bitmap_manager_.get(),
3110 gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false));
3112 gfx::Size size(2, 2);
3113 gfx::Vector2d offset(0, 0);
3114 ResourceFormat format = RGBA_8888;
3115 ResourceId id = 0;
3116 uint8_t pixels[16] = { 0 };
3117 int texture_id = 123;
3119 // Lazy allocation. Don't allocate when creating the resource.
3120 id = resource_provider->CreateResource(
3121 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
3123 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3124 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(1);
3125 resource_provider->CreateForTesting(id);
3127 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3128 resource_provider->DeleteResource(id);
3130 Mock::VerifyAndClearExpectations(context);
3132 // Do allocate when we set the pixels.
3133 id = resource_provider->CreateResource(
3134 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
3136 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3137 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(3);
3138 EXPECT_CALL(*context, texImage2D(_, _, _, 2, 2, _, _, _, _)).Times(1);
3139 EXPECT_CALL(*context, texSubImage2D(_, _, _, _, 2, 2, _, _, _)).Times(1);
3140 resource_provider->CopyToResource(id, pixels, size);
3142 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3143 resource_provider->DeleteResource(id);
3145 Mock::VerifyAndClearExpectations(context);
3147 // Same for async version.
3148 id = resource_provider->CreateResource(
3149 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
3150 resource_provider->AcquirePixelBuffer(id);
3152 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3153 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
3154 EXPECT_CALL(*context, asyncTexImage2DCHROMIUM(_, _, _, 2, 2, _, _, _, _))
3155 .Times(1);
3156 resource_provider->BeginSetPixels(id);
3157 ASSERT_TRUE(resource_provider->DidSetPixelsComplete(id));
3159 resource_provider->ReleasePixelBuffer(id);
3161 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3162 resource_provider->DeleteResource(id);
3164 Mock::VerifyAndClearExpectations(context);
3167 TEST_P(ResourceProviderTest, TextureAllocationHint) {
3168 // Only for GL textures.
3169 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
3170 return;
3171 scoped_ptr<AllocationTrackingContext3D> context_owned(
3172 new StrictMock<AllocationTrackingContext3D>);
3173 AllocationTrackingContext3D* context = context_owned.get();
3174 context->set_support_texture_storage(true);
3175 context->set_support_texture_usage(true);
3177 FakeOutputSurfaceClient output_surface_client;
3178 scoped_ptr<OutputSurface> output_surface(
3179 FakeOutputSurface::Create3d(context_owned.Pass()));
3180 CHECK(output_surface->BindToClient(&output_surface_client));
3182 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
3183 output_surface.get(), shared_bitmap_manager_.get(),
3184 gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false));
3186 gfx::Size size(2, 2);
3188 const ResourceFormat formats[2] = {RGBA_8888, BGRA_8888};
3189 const ResourceProvider::TextureHint hints[4] = {
3190 ResourceProvider::TEXTURE_HINT_DEFAULT,
3191 ResourceProvider::TEXTURE_HINT_IMMUTABLE,
3192 ResourceProvider::TEXTURE_HINT_FRAMEBUFFER,
3193 ResourceProvider::TEXTURE_HINT_IMMUTABLE_FRAMEBUFFER,
3195 for (size_t i = 0; i < arraysize(formats); ++i) {
3196 for (GLuint texture_id = 1; texture_id <= arraysize(hints); ++texture_id) {
3197 // Lazy allocation. Don't allocate when creating the resource.
3198 ResourceId id = resource_provider->CreateResource(
3199 size, GL_CLAMP_TO_EDGE, hints[texture_id - 1], formats[i]);
3201 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3202 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
3203 bool is_immutable_hint =
3204 hints[texture_id - 1] & ResourceProvider::TEXTURE_HINT_IMMUTABLE;
3205 bool support_immutable_texture =
3206 is_immutable_hint && formats[i] == RGBA_8888;
3207 EXPECT_CALL(*context, texStorage2DEXT(_, _, _, 2, 2))
3208 .Times(support_immutable_texture ? 1 : 0);
3209 EXPECT_CALL(*context, texImage2D(_, _, _, 2, 2, _, _, _, _))
3210 .Times(support_immutable_texture ? 0 : 1);
3211 resource_provider->AllocateForTesting(id);
3213 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3214 resource_provider->DeleteResource(id);
3216 Mock::VerifyAndClearExpectations(context);
3221 TEST_P(ResourceProviderTest, TextureAllocationHint_BGRA) {
3222 // Only for GL textures.
3223 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
3224 return;
3225 scoped_ptr<AllocationTrackingContext3D> context_owned(
3226 new StrictMock<AllocationTrackingContext3D>);
3227 AllocationTrackingContext3D* context = context_owned.get();
3228 context->set_support_texture_format_bgra8888(true);
3229 context->set_support_texture_storage(true);
3230 context->set_support_texture_usage(true);
3232 FakeOutputSurfaceClient output_surface_client;
3233 scoped_ptr<OutputSurface> output_surface(
3234 FakeOutputSurface::Create3d(context_owned.Pass()));
3235 CHECK(output_surface->BindToClient(&output_surface_client));
3237 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
3238 output_surface.get(), shared_bitmap_manager_.get(),
3239 gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false));
3241 gfx::Size size(2, 2);
3242 const ResourceFormat formats[2] = {RGBA_8888, BGRA_8888};
3244 const ResourceProvider::TextureHint hints[4] = {
3245 ResourceProvider::TEXTURE_HINT_DEFAULT,
3246 ResourceProvider::TEXTURE_HINT_IMMUTABLE,
3247 ResourceProvider::TEXTURE_HINT_FRAMEBUFFER,
3248 ResourceProvider::TEXTURE_HINT_IMMUTABLE_FRAMEBUFFER,
3250 for (size_t i = 0; i < arraysize(formats); ++i) {
3251 for (GLuint texture_id = 1; texture_id <= arraysize(hints); ++texture_id) {
3252 // Lazy allocation. Don't allocate when creating the resource.
3253 ResourceId id = resource_provider->CreateResource(
3254 size, GL_CLAMP_TO_EDGE, hints[texture_id - 1], formats[i]);
3256 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3257 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
3258 bool is_immutable_hint =
3259 hints[texture_id - 1] & ResourceProvider::TEXTURE_HINT_IMMUTABLE;
3260 EXPECT_CALL(*context, texStorage2DEXT(_, _, _, 2, 2))
3261 .Times(is_immutable_hint ? 1 : 0);
3262 EXPECT_CALL(*context, texImage2D(_, _, _, 2, 2, _, _, _, _))
3263 .Times(is_immutable_hint ? 0 : 1);
3264 resource_provider->AllocateForTesting(id);
3266 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3267 resource_provider->DeleteResource(id);
3269 Mock::VerifyAndClearExpectations(context);
3274 TEST_P(ResourceProviderTest, PixelBuffer_GLTexture) {
3275 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
3276 return;
3277 scoped_ptr<AllocationTrackingContext3D> context_owned(
3278 new StrictMock<AllocationTrackingContext3D>);
3279 AllocationTrackingContext3D* context = context_owned.get();
3281 FakeOutputSurfaceClient output_surface_client;
3282 scoped_ptr<OutputSurface> output_surface(
3283 FakeOutputSurface::Create3d(context_owned.Pass()));
3284 CHECK(output_surface->BindToClient(&output_surface_client));
3286 gfx::Size size(2, 2);
3287 ResourceFormat format = RGBA_8888;
3288 ResourceId id = 0;
3289 int texture_id = 123;
3291 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
3292 output_surface.get(), shared_bitmap_manager_.get(),
3293 gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false));
3295 id = resource_provider->CreateResource(
3296 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
3297 resource_provider->AcquirePixelBuffer(id);
3299 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3300 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
3301 EXPECT_CALL(*context, asyncTexImage2DCHROMIUM(_, _, _, 2, 2, _, _, _, _))
3302 .Times(1);
3303 resource_provider->BeginSetPixels(id);
3305 EXPECT_TRUE(resource_provider->DidSetPixelsComplete(id));
3307 resource_provider->ReleasePixelBuffer(id);
3309 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3310 resource_provider->DeleteResource(id);
3312 Mock::VerifyAndClearExpectations(context);
3315 TEST_P(ResourceProviderTest, ForcingAsyncUploadToComplete) {
3316 // Only for GL textures.
3317 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
3318 return;
3319 scoped_ptr<AllocationTrackingContext3D> context_owned(
3320 new StrictMock<AllocationTrackingContext3D>);
3321 AllocationTrackingContext3D* context = context_owned.get();
3323 FakeOutputSurfaceClient output_surface_client;
3324 scoped_ptr<OutputSurface> output_surface(
3325 FakeOutputSurface::Create3d(context_owned.Pass()));
3326 CHECK(output_surface->BindToClient(&output_surface_client));
3328 gfx::Size size(2, 2);
3329 ResourceFormat format = RGBA_8888;
3330 ResourceId id = 0;
3331 int texture_id = 123;
3333 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
3334 output_surface.get(), shared_bitmap_manager_.get(),
3335 gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false));
3337 id = resource_provider->CreateResource(
3338 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
3339 resource_provider->AcquirePixelBuffer(id);
3341 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3342 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
3343 EXPECT_CALL(*context, asyncTexImage2DCHROMIUM(_, _, _, 2, 2, _, _, _, _))
3344 .Times(1);
3345 resource_provider->BeginSetPixels(id);
3347 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(1);
3348 EXPECT_CALL(*context, waitAsyncTexImage2DCHROMIUM(GL_TEXTURE_2D)).Times(1);
3349 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, 0)).Times(1);
3350 resource_provider->ForceSetPixelsToComplete(id);
3352 resource_provider->ReleasePixelBuffer(id);
3354 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3355 resource_provider->DeleteResource(id);
3357 Mock::VerifyAndClearExpectations(context);
3360 TEST_P(ResourceProviderTest, PixelBufferLostContext) {
3361 scoped_ptr<AllocationTrackingContext3D> context_owned(
3362 new NiceMock<AllocationTrackingContext3D>);
3363 AllocationTrackingContext3D* context = context_owned.get();
3365 FakeOutputSurfaceClient output_surface_client;
3366 scoped_ptr<OutputSurface> output_surface(
3367 FakeOutputSurface::Create3d(context_owned.Pass()));
3368 CHECK(output_surface->BindToClient(&output_surface_client));
3370 gfx::Size size(2, 2);
3371 ResourceFormat format = RGBA_8888;
3372 ResourceId id = 0;
3373 int texture_id = 123;
3375 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
3376 output_surface.get(), shared_bitmap_manager_.get(),
3377 gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false));
3379 EXPECT_CALL(*context, NextTextureId()).WillRepeatedly(Return(texture_id));
3381 id = resource_provider->CreateResource(
3382 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
3383 context->loseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB,
3384 GL_INNOCENT_CONTEXT_RESET_ARB);
3386 resource_provider->AcquirePixelBuffer(id);
3387 int stride;
3388 void* buffer = resource_provider->MapPixelBuffer(id, &stride);
3389 EXPECT_FALSE(buffer);
3390 resource_provider->UnmapPixelBuffer(id);
3391 Mock::VerifyAndClearExpectations(context);
3394 TEST_P(ResourceProviderTest, Image_GLTexture) {
3395 // Only for GL textures.
3396 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
3397 return;
3398 scoped_ptr<AllocationTrackingContext3D> context_owned(
3399 new StrictMock<AllocationTrackingContext3D>);
3400 AllocationTrackingContext3D* context = context_owned.get();
3402 FakeOutputSurfaceClient output_surface_client;
3403 scoped_ptr<OutputSurface> output_surface(
3404 FakeOutputSurface::Create3d(context_owned.Pass()));
3405 CHECK(output_surface->BindToClient(&output_surface_client));
3407 const int kWidth = 2;
3408 const int kHeight = 2;
3409 gfx::Size size(kWidth, kHeight);
3410 ResourceFormat format = RGBA_8888;
3411 ResourceId id = 0;
3412 const unsigned kTextureId = 123u;
3413 const unsigned kImageId = 234u;
3415 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
3416 output_surface.get(), shared_bitmap_manager_.get(),
3417 gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false));
3419 id = resource_provider->CreateResource(
3420 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
3422 EXPECT_CALL(*context, createImageCHROMIUM(_, kWidth, kHeight, GL_RGBA))
3423 .WillOnce(Return(kImageId))
3424 .RetiresOnSaturation();
3426 ResourceProvider::ScopedWriteLockGpuMemoryBuffer lock(
3427 resource_provider.get(), id);
3428 EXPECT_TRUE(lock.GetGpuMemoryBuffer());
3431 EXPECT_CALL(*context, NextTextureId())
3432 .WillOnce(Return(kTextureId))
3433 .RetiresOnSaturation();
3434 // Once in CreateTextureId and once in BindForSampling
3435 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kTextureId)).Times(2)
3436 .RetiresOnSaturation();
3437 EXPECT_CALL(*context, bindTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId))
3438 .Times(1)
3439 .RetiresOnSaturation();
3441 ResourceProvider::ScopedSamplerGL lock_gl(
3442 resource_provider.get(), id, GL_TEXTURE_2D, GL_LINEAR);
3443 EXPECT_EQ(kTextureId, lock_gl.texture_id());
3447 ResourceProvider::ScopedWriteLockGpuMemoryBuffer lock(
3448 resource_provider.get(), id);
3449 EXPECT_TRUE(lock.GetGpuMemoryBuffer());
3452 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kTextureId)).Times(1)
3453 .RetiresOnSaturation();
3454 EXPECT_CALL(*context, releaseTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId))
3455 .Times(1)
3456 .RetiresOnSaturation();
3457 EXPECT_CALL(*context, bindTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId))
3458 .Times(1)
3459 .RetiresOnSaturation();
3460 EXPECT_CALL(*context, RetireTextureId(kTextureId))
3461 .Times(1)
3462 .RetiresOnSaturation();
3464 ResourceProvider::ScopedSamplerGL lock_gl(
3465 resource_provider.get(), id, GL_TEXTURE_2D, GL_LINEAR);
3466 EXPECT_EQ(kTextureId, lock_gl.texture_id());
3469 EXPECT_CALL(*context, destroyImageCHROMIUM(kImageId))
3470 .Times(1)
3471 .RetiresOnSaturation();
3474 TEST_P(ResourceProviderTest, CopyResource_GLTexture) {
3475 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
3476 return;
3477 scoped_ptr<AllocationTrackingContext3D> context_owned(
3478 new StrictMock<AllocationTrackingContext3D>);
3479 AllocationTrackingContext3D* context = context_owned.get();
3480 context_owned->set_support_sync_query(true);
3482 FakeOutputSurfaceClient output_surface_client;
3483 scoped_ptr<OutputSurface> output_surface(
3484 FakeOutputSurface::Create3d(context_owned.Pass()));
3485 ASSERT_TRUE(output_surface->BindToClient(&output_surface_client));
3487 const int kWidth = 2;
3488 const int kHeight = 2;
3489 gfx::Size size(kWidth, kHeight);
3490 ResourceFormat format = RGBA_8888;
3491 ResourceId source_id = 0;
3492 ResourceId dest_id = 0;
3493 const unsigned kSourceTextureId = 123u;
3494 const unsigned kDestTextureId = 321u;
3495 const unsigned kImageId = 234u;
3497 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
3498 output_surface.get(), shared_bitmap_manager_.get(),
3499 gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false));
3501 source_id = resource_provider->CreateResource(
3502 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
3504 EXPECT_CALL(*context, createImageCHROMIUM(_, kWidth, kHeight, GL_RGBA))
3505 .WillOnce(Return(kImageId))
3506 .RetiresOnSaturation();
3508 ResourceProvider::ScopedWriteLockGpuMemoryBuffer lock(
3509 resource_provider.get(), source_id);
3510 EXPECT_TRUE(lock.GetGpuMemoryBuffer());
3512 Mock::VerifyAndClearExpectations(context);
3514 dest_id = resource_provider->CreateResource(
3515 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, format);
3517 EXPECT_CALL(*context, NextTextureId())
3518 .WillOnce(Return(kDestTextureId))
3519 .RetiresOnSaturation();
3520 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kDestTextureId))
3521 .Times(2)
3522 .RetiresOnSaturation();
3523 EXPECT_CALL(*context, texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA,
3524 GL_UNSIGNED_BYTE, nullptr))
3525 .Times(1)
3526 .RetiresOnSaturation();
3527 EXPECT_CALL(*context, NextTextureId())
3528 .WillOnce(Return(kSourceTextureId))
3529 .RetiresOnSaturation();
3530 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kSourceTextureId))
3531 .Times(2)
3532 .RetiresOnSaturation();
3533 EXPECT_CALL(*context, bindTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId))
3534 .Times(1)
3535 .RetiresOnSaturation();
3536 resource_provider->CopyResource(source_id, dest_id, gfx::Rect(size));
3537 Mock::VerifyAndClearExpectations(context);
3539 EXPECT_CALL(*context, destroyImageCHROMIUM(kImageId))
3540 .Times(1)
3541 .RetiresOnSaturation();
3542 EXPECT_CALL(*context, RetireTextureId(kSourceTextureId))
3543 .Times(1)
3544 .RetiresOnSaturation();
3545 EXPECT_CALL(*context, RetireTextureId(kDestTextureId))
3546 .Times(1)
3547 .RetiresOnSaturation();
3548 resource_provider->DeleteResource(source_id);
3549 resource_provider->DeleteResource(dest_id);
3552 TEST_P(ResourceProviderTest, CompressedTextureETC1Allocate) {
3553 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
3554 return;
3556 scoped_ptr<AllocationTrackingContext3D> context_owned(
3557 new AllocationTrackingContext3D);
3558 AllocationTrackingContext3D* context = context_owned.get();
3559 context_owned->set_support_compressed_texture_etc1(true);
3561 FakeOutputSurfaceClient output_surface_client;
3562 scoped_ptr<OutputSurface> output_surface(
3563 FakeOutputSurface::Create3d(context_owned.Pass()));
3564 CHECK(output_surface->BindToClient(&output_surface_client));
3566 gfx::Size size(4, 4);
3567 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
3568 output_surface.get(), shared_bitmap_manager_.get(),
3569 gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false));
3570 int texture_id = 123;
3572 ResourceId id = resource_provider->CreateResource(
3573 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, ETC1);
3574 EXPECT_NE(0u, id);
3575 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3576 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
3577 resource_provider->AllocateForTesting(id);
3579 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3580 resource_provider->DeleteResource(id);
3583 TEST_P(ResourceProviderTest, CompressedTextureETC1Upload) {
3584 if (GetParam() != ResourceProvider::RESOURCE_TYPE_GL_TEXTURE)
3585 return;
3587 scoped_ptr<AllocationTrackingContext3D> context_owned(
3588 new AllocationTrackingContext3D);
3589 AllocationTrackingContext3D* context = context_owned.get();
3590 context_owned->set_support_compressed_texture_etc1(true);
3592 FakeOutputSurfaceClient output_surface_client;
3593 scoped_ptr<OutputSurface> output_surface(
3594 FakeOutputSurface::Create3d(context_owned.Pass()));
3595 CHECK(output_surface->BindToClient(&output_surface_client));
3597 gfx::Size size(4, 4);
3598 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
3599 output_surface.get(), shared_bitmap_manager_.get(),
3600 gpu_memory_buffer_manager_.get(), NULL, 0, false, 1, false));
3601 int texture_id = 123;
3602 uint8_t pixels[8];
3604 ResourceId id = resource_provider->CreateResource(
3605 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE, ETC1);
3606 EXPECT_NE(0u, id);
3607 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3608 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(3);
3609 EXPECT_CALL(*context,
3610 compressedTexImage2D(
3611 _, 0, _, size.width(), size.height(), _, _, _)).Times(1);
3612 resource_provider->CopyToResource(id, pixels, size);
3614 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3615 resource_provider->DeleteResource(id);
3618 INSTANTIATE_TEST_CASE_P(
3619 ResourceProviderTests,
3620 ResourceProviderTest,
3621 ::testing::Values(ResourceProvider::RESOURCE_TYPE_GL_TEXTURE,
3622 ResourceProvider::RESOURCE_TYPE_BITMAP));
3624 class TextureIdAllocationTrackingContext : public TestWebGraphicsContext3D {
3625 public:
3626 GLuint NextTextureId() override {
3627 base::AutoLock lock(namespace_->lock);
3628 return namespace_->next_texture_id++;
3630 void RetireTextureId(GLuint) override {}
3631 GLuint PeekTextureId() {
3632 base::AutoLock lock(namespace_->lock);
3633 return namespace_->next_texture_id;
3637 TEST(ResourceProviderTest, TextureAllocationChunkSize) {
3638 scoped_ptr<TextureIdAllocationTrackingContext> context_owned(
3639 new TextureIdAllocationTrackingContext);
3640 TextureIdAllocationTrackingContext* context = context_owned.get();
3642 FakeOutputSurfaceClient output_surface_client;
3643 scoped_ptr<OutputSurface> output_surface(
3644 FakeOutputSurface::Create3d(context_owned.Pass()));
3645 CHECK(output_surface->BindToClient(&output_surface_client));
3646 scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
3647 new TestSharedBitmapManager());
3649 gfx::Size size(1, 1);
3650 ResourceFormat format = RGBA_8888;
3653 size_t kTextureAllocationChunkSize = 1;
3654 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
3655 output_surface.get(), shared_bitmap_manager.get(), NULL, NULL, 0, false,
3656 kTextureAllocationChunkSize, false));
3658 ResourceId id = resource_provider->CreateResource(
3659 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE,
3660 format);
3661 resource_provider->AllocateForTesting(id);
3662 Mock::VerifyAndClearExpectations(context);
3664 DCHECK_EQ(2u, context->PeekTextureId());
3665 resource_provider->DeleteResource(id);
3669 size_t kTextureAllocationChunkSize = 8;
3670 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
3671 output_surface.get(), shared_bitmap_manager.get(), NULL, NULL, 0, false,
3672 kTextureAllocationChunkSize, false));
3674 ResourceId id = resource_provider->CreateResource(
3675 size, GL_CLAMP_TO_EDGE, ResourceProvider::TEXTURE_HINT_IMMUTABLE,
3676 format);
3677 resource_provider->AllocateForTesting(id);
3678 Mock::VerifyAndClearExpectations(context);
3680 DCHECK_EQ(10u, context->PeekTextureId());
3681 resource_provider->DeleteResource(id);
3685 } // namespace
3686 } // namespace cc