[NaCl SDK]: use standard __BEGIN_DECLS macros in sys/select.h
[chromium-blink-merge.git] / cc / resources / resource_provider_unittest.cc
blobe10e01ccdcac04db9c6d429deee0350995bf2e51
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_shared_bitmap_manager.h"
23 #include "cc/test/test_texture.h"
24 #include "cc/test/test_web_graphics_context_3d.h"
25 #include "cc/trees/blocking_task_runner.h"
26 #include "gpu/GLES2/gl2extchromium.h"
27 #include "testing/gmock/include/gmock/gmock.h"
28 #include "testing/gtest/include/gtest/gtest.h"
29 #include "third_party/khronos/GLES2/gl2.h"
30 #include "third_party/khronos/GLES2/gl2ext.h"
31 #include "ui/gfx/rect.h"
33 using testing::Mock;
34 using testing::NiceMock;
35 using testing::Return;
36 using testing::SetArgPointee;
37 using testing::StrictMock;
38 using testing::_;
40 namespace cc {
41 namespace {
43 static void EmptyReleaseCallback(uint32 sync_point,
44 bool lost_resource,
45 BlockingTaskRunner* main_thread_task_runner) {
48 static void ReleaseCallback(
49 uint32* release_sync_point,
50 bool* release_lost_resource,
51 BlockingTaskRunner** release_main_thread_task_runner,
52 uint32 sync_point,
53 bool lost_resource,
54 BlockingTaskRunner* main_thread_task_runner) {
55 *release_sync_point = sync_point;
56 *release_lost_resource = lost_resource;
57 *release_main_thread_task_runner = main_thread_task_runner;
60 static void SharedMemoryReleaseCallback(
61 scoped_ptr<base::SharedMemory> memory,
62 uint32 sync_point,
63 bool lost_resource,
64 BlockingTaskRunner* main_thread_task_runner) {
67 static void ReleaseSharedMemoryCallback(
68 scoped_ptr<base::SharedMemory> shared_memory,
69 bool* release_called,
70 uint32* release_sync_point,
71 bool* lost_resource_result,
72 uint32 sync_point,
73 bool lost_resource,
74 BlockingTaskRunner* main_thread_task_runner) {
75 *release_called = true;
76 *release_sync_point = sync_point;
77 *lost_resource_result = lost_resource;
80 static scoped_ptr<base::SharedMemory> CreateAndFillSharedMemory(
81 const gfx::Size& size,
82 uint32_t value) {
83 scoped_ptr<base::SharedMemory> shared_memory(new base::SharedMemory);
84 CHECK(shared_memory->CreateAndMapAnonymous(4 * size.GetArea()));
85 uint32_t* pixels = reinterpret_cast<uint32_t*>(shared_memory->memory());
86 CHECK(pixels);
87 std::fill_n(pixels, size.GetArea(), value);
88 return shared_memory.Pass();
91 class TextureStateTrackingContext : public TestWebGraphicsContext3D {
92 public:
93 MOCK_METHOD2(bindTexture, void(GLenum target, GLuint texture));
94 MOCK_METHOD3(texParameteri, void(GLenum target, GLenum pname, GLint param));
95 MOCK_METHOD1(waitSyncPoint, void(GLuint sync_point));
96 MOCK_METHOD0(insertSyncPoint, GLuint(void));
97 MOCK_METHOD2(produceTextureCHROMIUM,
98 void(GLenum target, const GLbyte* mailbox));
99 MOCK_METHOD2(consumeTextureCHROMIUM,
100 void(GLenum target, const GLbyte* mailbox));
102 // Force all textures to be consecutive numbers starting at "1",
103 // so we easily can test for them.
104 virtual GLuint NextTextureId() OVERRIDE {
105 base::AutoLock lock(namespace_->lock);
106 return namespace_->next_texture_id++;
108 virtual void RetireTextureId(GLuint) OVERRIDE {}
111 // Shared data between multiple ResourceProviderContext. This contains mailbox
112 // contents as well as information about sync points.
113 class ContextSharedData {
114 public:
115 static scoped_ptr<ContextSharedData> Create() {
116 return make_scoped_ptr(new ContextSharedData());
119 uint32 InsertSyncPoint() { return next_sync_point_++; }
121 void GenMailbox(GLbyte* mailbox) {
122 memset(mailbox, 0, GL_MAILBOX_SIZE_CHROMIUM);
123 memcpy(mailbox, &next_mailbox_, sizeof(next_mailbox_));
124 ++next_mailbox_;
127 void ProduceTexture(const GLbyte* mailbox_name,
128 uint32 sync_point,
129 scoped_refptr<TestTexture> texture) {
130 unsigned mailbox = 0;
131 memcpy(&mailbox, mailbox_name, sizeof(mailbox));
132 ASSERT_TRUE(mailbox && mailbox < next_mailbox_);
133 textures_[mailbox] = texture;
134 ASSERT_LT(sync_point_for_mailbox_[mailbox], sync_point);
135 sync_point_for_mailbox_[mailbox] = sync_point;
138 scoped_refptr<TestTexture> ConsumeTexture(const GLbyte* mailbox_name,
139 uint32 sync_point) {
140 unsigned mailbox = 0;
141 memcpy(&mailbox, mailbox_name, sizeof(mailbox));
142 DCHECK(mailbox && mailbox < next_mailbox_);
144 // If the latest sync point the context has waited on is before the sync
145 // point for when the mailbox was set, pretend we never saw that
146 // ProduceTexture.
147 if (sync_point_for_mailbox_[mailbox] > sync_point) {
148 NOTREACHED();
149 return scoped_refptr<TestTexture>();
151 return textures_[mailbox];
154 private:
155 ContextSharedData() : next_sync_point_(1), next_mailbox_(1) {}
157 uint32 next_sync_point_;
158 unsigned next_mailbox_;
159 typedef base::hash_map<unsigned, scoped_refptr<TestTexture> > TextureMap;
160 TextureMap textures_;
161 base::hash_map<unsigned, uint32> sync_point_for_mailbox_;
164 class ResourceProviderContext : public TestWebGraphicsContext3D {
165 public:
166 static scoped_ptr<ResourceProviderContext> Create(
167 ContextSharedData* shared_data) {
168 return make_scoped_ptr(new ResourceProviderContext(shared_data));
171 virtual GLuint insertSyncPoint() OVERRIDE {
172 uint32 sync_point = shared_data_->InsertSyncPoint();
173 // Commit the produceTextureCHROMIUM calls at this point, so that
174 // they're associated with the sync point.
175 for (PendingProduceTextureList::iterator it =
176 pending_produce_textures_.begin();
177 it != pending_produce_textures_.end();
178 ++it) {
179 shared_data_->ProduceTexture(
180 (*it)->mailbox, sync_point, (*it)->texture);
182 pending_produce_textures_.clear();
183 return sync_point;
186 virtual void waitSyncPoint(GLuint sync_point) OVERRIDE {
187 last_waited_sync_point_ = std::max(sync_point, last_waited_sync_point_);
190 unsigned last_waited_sync_point() const { return last_waited_sync_point_; }
192 virtual void texStorage2DEXT(GLenum target,
193 GLint levels,
194 GLuint internalformat,
195 GLint width,
196 GLint height) OVERRIDE {
197 CheckTextureIsBound(target);
198 ASSERT_EQ(static_cast<unsigned>(GL_TEXTURE_2D), target);
199 ASSERT_EQ(1, levels);
200 GLenum format = GL_RGBA;
201 switch (internalformat) {
202 case GL_RGBA8_OES:
203 break;
204 case GL_BGRA8_EXT:
205 format = GL_BGRA_EXT;
206 break;
207 default:
208 NOTREACHED();
210 AllocateTexture(gfx::Size(width, height), format);
213 virtual void texImage2D(GLenum target,
214 GLint level,
215 GLenum internalformat,
216 GLsizei width,
217 GLsizei height,
218 GLint border,
219 GLenum format,
220 GLenum type,
221 const void* pixels) OVERRIDE {
222 CheckTextureIsBound(target);
223 ASSERT_EQ(static_cast<unsigned>(GL_TEXTURE_2D), target);
224 ASSERT_FALSE(level);
225 ASSERT_EQ(internalformat, format);
226 ASSERT_FALSE(border);
227 ASSERT_EQ(static_cast<unsigned>(GL_UNSIGNED_BYTE), type);
228 AllocateTexture(gfx::Size(width, height), format);
229 if (pixels)
230 SetPixels(0, 0, width, height, pixels);
233 virtual void texSubImage2D(GLenum target,
234 GLint level,
235 GLint xoffset,
236 GLint yoffset,
237 GLsizei width,
238 GLsizei height,
239 GLenum format,
240 GLenum type,
241 const void* pixels) OVERRIDE {
242 CheckTextureIsBound(target);
243 ASSERT_EQ(static_cast<unsigned>(GL_TEXTURE_2D), target);
244 ASSERT_FALSE(level);
245 ASSERT_EQ(static_cast<unsigned>(GL_UNSIGNED_BYTE), type);
247 base::AutoLock lock_for_texture_access(namespace_->lock);
248 ASSERT_EQ(GLDataFormat(BoundTexture(target)->format), format);
250 ASSERT_TRUE(pixels);
251 SetPixels(xoffset, yoffset, width, height, pixels);
254 virtual void genMailboxCHROMIUM(GLbyte* mailbox) OVERRIDE {
255 return shared_data_->GenMailbox(mailbox);
258 virtual void produceTextureCHROMIUM(GLenum target,
259 const GLbyte* mailbox) OVERRIDE {
260 CheckTextureIsBound(target);
262 // Delay moving the texture into the mailbox until the next
263 // InsertSyncPoint, so that it is not visible to other contexts that
264 // haven't waited on that sync point.
265 scoped_ptr<PendingProduceTexture> pending(new PendingProduceTexture);
266 memcpy(pending->mailbox, mailbox, sizeof(pending->mailbox));
267 base::AutoLock lock_for_texture_access(namespace_->lock);
268 pending->texture = BoundTexture(target);
269 pending_produce_textures_.push_back(pending.Pass());
272 virtual void consumeTextureCHROMIUM(GLenum target,
273 const GLbyte* mailbox) OVERRIDE {
274 CheckTextureIsBound(target);
275 base::AutoLock lock_for_texture_access(namespace_->lock);
276 scoped_refptr<TestTexture> texture =
277 shared_data_->ConsumeTexture(mailbox, last_waited_sync_point_);
278 namespace_->textures.Replace(BoundTextureId(target), texture);
281 void GetPixels(const gfx::Size& size,
282 ResourceFormat format,
283 uint8_t* pixels) {
284 CheckTextureIsBound(GL_TEXTURE_2D);
285 base::AutoLock lock_for_texture_access(namespace_->lock);
286 scoped_refptr<TestTexture> texture = BoundTexture(GL_TEXTURE_2D);
287 ASSERT_EQ(texture->size, size);
288 ASSERT_EQ(texture->format, format);
289 memcpy(pixels, texture->data.get(), TextureSizeBytes(size, format));
292 protected:
293 explicit ResourceProviderContext(ContextSharedData* shared_data)
294 : shared_data_(shared_data),
295 last_waited_sync_point_(0) {}
297 private:
298 void AllocateTexture(const gfx::Size& size, GLenum format) {
299 CheckTextureIsBound(GL_TEXTURE_2D);
300 ResourceFormat texture_format = RGBA_8888;
301 switch (format) {
302 case GL_RGBA:
303 texture_format = RGBA_8888;
304 break;
305 case GL_BGRA_EXT:
306 texture_format = BGRA_8888;
307 break;
309 base::AutoLock lock_for_texture_access(namespace_->lock);
310 BoundTexture(GL_TEXTURE_2D)->Reallocate(size, texture_format);
313 void SetPixels(int xoffset,
314 int yoffset,
315 int width,
316 int height,
317 const void* pixels) {
318 CheckTextureIsBound(GL_TEXTURE_2D);
319 base::AutoLock lock_for_texture_access(namespace_->lock);
320 scoped_refptr<TestTexture> texture = BoundTexture(GL_TEXTURE_2D);
321 ASSERT_TRUE(texture->data.get());
322 ASSERT_TRUE(xoffset >= 0 && xoffset + width <= texture->size.width());
323 ASSERT_TRUE(yoffset >= 0 && yoffset + height <= texture->size.height());
324 ASSERT_TRUE(pixels);
325 size_t in_pitch = TextureSizeBytes(gfx::Size(width, 1), texture->format);
326 size_t out_pitch =
327 TextureSizeBytes(gfx::Size(texture->size.width(), 1), texture->format);
328 uint8_t* dest = texture->data.get() + yoffset * out_pitch +
329 TextureSizeBytes(gfx::Size(xoffset, 1), texture->format);
330 const uint8_t* src = static_cast<const uint8_t*>(pixels);
331 for (int i = 0; i < height; ++i) {
332 memcpy(dest, src, in_pitch);
333 dest += out_pitch;
334 src += in_pitch;
338 struct PendingProduceTexture {
339 GLbyte mailbox[GL_MAILBOX_SIZE_CHROMIUM];
340 scoped_refptr<TestTexture> texture;
342 typedef ScopedPtrDeque<PendingProduceTexture> PendingProduceTextureList;
343 ContextSharedData* shared_data_;
344 GLuint last_waited_sync_point_;
345 PendingProduceTextureList pending_produce_textures_;
348 void GetResourcePixels(ResourceProvider* resource_provider,
349 ResourceProviderContext* context,
350 ResourceProvider::ResourceId id,
351 const gfx::Size& size,
352 ResourceFormat format,
353 uint8_t* pixels) {
354 resource_provider->WaitSyncPointIfNeeded(id);
355 switch (resource_provider->default_resource_type()) {
356 case ResourceProvider::GLTexture: {
357 ResourceProvider::ScopedReadLockGL lock_gl(resource_provider, id);
358 ASSERT_NE(0U, lock_gl.texture_id());
359 context->bindTexture(GL_TEXTURE_2D, lock_gl.texture_id());
360 context->GetPixels(size, format, pixels);
361 break;
363 case ResourceProvider::Bitmap: {
364 ResourceProvider::ScopedReadLockSoftware lock_software(resource_provider,
365 id);
366 memcpy(pixels,
367 lock_software.sk_bitmap()->getPixels(),
368 lock_software.sk_bitmap()->getSize());
369 break;
371 case ResourceProvider::InvalidType:
372 NOTREACHED();
373 break;
377 class ResourceProviderTest
378 : public testing::TestWithParam<ResourceProvider::ResourceType> {
379 public:
380 ResourceProviderTest()
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::GLTexture: {
387 scoped_ptr<ResourceProviderContext> context3d(
388 ResourceProviderContext::Create(shared_data_.get()));
389 context3d_ = context3d.get();
391 scoped_refptr<TestContextProvider> context_provider =
392 TestContextProvider::Create(
393 context3d.PassAs<TestWebGraphicsContext3D>());
395 output_surface_ = FakeOutputSurface::Create3d(context_provider);
397 scoped_ptr<ResourceProviderContext> child_context_owned =
398 ResourceProviderContext::Create(shared_data_.get());
399 child_context_ = child_context_owned.get();
400 child_output_surface_ = FakeOutputSurface::Create3d(
401 child_context_owned.PassAs<TestWebGraphicsContext3D>());
402 break;
404 case ResourceProvider::Bitmap:
405 output_surface_ = FakeOutputSurface::CreateSoftware(
406 make_scoped_ptr(new SoftwareOutputDevice));
407 child_output_surface_ = FakeOutputSurface::CreateSoftware(
408 make_scoped_ptr(new SoftwareOutputDevice));
409 break;
410 case ResourceProvider::InvalidType:
411 NOTREACHED();
412 break;
414 CHECK(output_surface_->BindToClient(&output_surface_client_));
415 CHECK(child_output_surface_->BindToClient(&child_output_surface_client_));
417 shared_bitmap_manager_.reset(new TestSharedBitmapManager());
419 resource_provider_ =
420 ResourceProvider::Create(output_surface_.get(),
421 shared_bitmap_manager_.get(),
422 main_thread_task_runner_.get(),
424 false,
426 false);
427 child_resource_provider_ =
428 ResourceProvider::Create(child_output_surface_.get(),
429 shared_bitmap_manager_.get(),
430 main_thread_task_runner_.get(),
432 false,
434 false);
437 static void CollectResources(ReturnedResourceArray* array,
438 const ReturnedResourceArray& returned,
439 BlockingTaskRunner* main_thread_task_runner) {
440 array->insert(array->end(), returned.begin(), returned.end());
443 static ReturnCallback GetReturnCallback(ReturnedResourceArray* array) {
444 return base::Bind(&ResourceProviderTest::CollectResources, array);
447 static void SetResourceFilter(ResourceProvider* resource_provider,
448 ResourceProvider::ResourceId id,
449 GLenum filter) {
450 ResourceProvider::ScopedSamplerGL sampler(
451 resource_provider, id, GL_TEXTURE_2D, filter);
454 ResourceProviderContext* context() { return context3d_; }
456 ResourceProvider::ResourceId CreateChildMailbox(uint32* release_sync_point,
457 bool* lost_resource,
458 bool* release_called,
459 uint32* sync_point) {
460 if (GetParam() == ResourceProvider::GLTexture) {
461 unsigned texture = child_context_->createTexture();
462 gpu::Mailbox gpu_mailbox;
463 child_context_->bindTexture(GL_TEXTURE_2D, texture);
464 child_context_->genMailboxCHROMIUM(gpu_mailbox.name);
465 child_context_->produceTextureCHROMIUM(GL_TEXTURE_2D, gpu_mailbox.name);
466 *sync_point = child_context_->insertSyncPoint();
467 EXPECT_LT(0u, *sync_point);
469 scoped_ptr<base::SharedMemory> shared_memory;
470 scoped_ptr<SingleReleaseCallbackImpl> callback =
471 SingleReleaseCallbackImpl::Create(
472 base::Bind(ReleaseSharedMemoryCallback,
473 base::Passed(&shared_memory),
474 release_called,
475 release_sync_point,
476 lost_resource));
477 return child_resource_provider_->CreateResourceFromTextureMailbox(
478 TextureMailbox(gpu_mailbox, GL_TEXTURE_2D, *sync_point),
479 callback.Pass());
480 } else {
481 gfx::Size size(64, 64);
482 scoped_ptr<base::SharedMemory> shared_memory(
483 CreateAndFillSharedMemory(size, 0));
485 base::SharedMemory* shared_memory_ptr = shared_memory.get();
486 scoped_ptr<SingleReleaseCallbackImpl> callback =
487 SingleReleaseCallbackImpl::Create(
488 base::Bind(ReleaseSharedMemoryCallback,
489 base::Passed(&shared_memory),
490 release_called,
491 release_sync_point,
492 lost_resource));
493 return child_resource_provider_->CreateResourceFromTextureMailbox(
494 TextureMailbox(shared_memory_ptr, size), callback.Pass());
498 protected:
499 scoped_ptr<ContextSharedData> shared_data_;
500 ResourceProviderContext* context3d_;
501 ResourceProviderContext* child_context_;
502 FakeOutputSurfaceClient output_surface_client_;
503 FakeOutputSurfaceClient child_output_surface_client_;
504 scoped_ptr<OutputSurface> output_surface_;
505 scoped_ptr<OutputSurface> child_output_surface_;
506 scoped_ptr<BlockingTaskRunner> main_thread_task_runner_;
507 scoped_ptr<ResourceProvider> resource_provider_;
508 scoped_ptr<ResourceProvider> child_resource_provider_;
509 scoped_ptr<TestSharedBitmapManager> shared_bitmap_manager_;
512 void CheckCreateResource(ResourceProvider::ResourceType expected_default_type,
513 ResourceProvider* resource_provider,
514 ResourceProviderContext* context) {
515 DCHECK_EQ(expected_default_type, resource_provider->default_resource_type());
517 gfx::Size size(1, 1);
518 ResourceFormat format = RGBA_8888;
519 size_t pixel_size = TextureSizeBytes(size, format);
520 ASSERT_EQ(4U, pixel_size);
522 ResourceProvider::ResourceId id = resource_provider->CreateResource(
523 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
524 EXPECT_EQ(1, static_cast<int>(resource_provider->num_resources()));
525 if (expected_default_type == ResourceProvider::GLTexture)
526 EXPECT_EQ(0u, context->NumTextures());
528 uint8_t data[4] = { 1, 2, 3, 4 };
529 gfx::Rect rect(size);
530 resource_provider->SetPixels(id, data, rect, rect, gfx::Vector2d());
531 if (expected_default_type == ResourceProvider::GLTexture)
532 EXPECT_EQ(1u, context->NumTextures());
534 uint8_t result[4] = { 0 };
535 GetResourcePixels(resource_provider, context, id, size, format, result);
536 EXPECT_EQ(0, memcmp(data, result, pixel_size));
538 resource_provider->DeleteResource(id);
539 EXPECT_EQ(0, static_cast<int>(resource_provider->num_resources()));
540 if (expected_default_type == ResourceProvider::GLTexture)
541 EXPECT_EQ(0u, context->NumTextures());
544 TEST_P(ResourceProviderTest, Basic) {
545 CheckCreateResource(GetParam(), resource_provider_.get(), context());
548 TEST_P(ResourceProviderTest, Upload) {
549 gfx::Size size(2, 2);
550 ResourceFormat format = RGBA_8888;
551 size_t pixel_size = TextureSizeBytes(size, format);
552 ASSERT_EQ(16U, pixel_size);
554 ResourceProvider::ResourceId id = resource_provider_->CreateResource(
555 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
557 uint8_t image[16] = { 0 };
558 gfx::Rect image_rect(size);
559 resource_provider_->SetPixels(
560 id, image, image_rect, image_rect, gfx::Vector2d());
562 for (uint8_t i = 0; i < pixel_size; ++i)
563 image[i] = i;
565 uint8_t result[16] = { 0 };
567 gfx::Rect source_rect(0, 0, 1, 1);
568 gfx::Vector2d dest_offset(0, 0);
569 resource_provider_->SetPixels(
570 id, image, image_rect, source_rect, dest_offset);
572 uint8_t expected[16] = { 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
573 GetResourcePixels(
574 resource_provider_.get(), context(), id, size, format, result);
575 EXPECT_EQ(0, memcmp(expected, result, pixel_size));
578 gfx::Rect source_rect(0, 0, 1, 1);
579 gfx::Vector2d dest_offset(1, 1);
580 resource_provider_->SetPixels(
581 id, image, image_rect, source_rect, dest_offset);
583 uint8_t expected[16] = { 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3 };
584 GetResourcePixels(
585 resource_provider_.get(), context(), id, size, format, result);
586 EXPECT_EQ(0, memcmp(expected, result, pixel_size));
589 gfx::Rect source_rect(1, 0, 1, 1);
590 gfx::Vector2d dest_offset(0, 1);
591 resource_provider_->SetPixels(
592 id, image, image_rect, source_rect, dest_offset);
594 uint8_t expected[16] = { 0, 1, 2, 3, 0, 0, 0, 0, 4, 5, 6, 7, 0, 1, 2, 3 };
595 GetResourcePixels(
596 resource_provider_.get(), context(), id, size, format, result);
597 EXPECT_EQ(0, memcmp(expected, result, pixel_size));
600 gfx::Rect offset_image_rect(gfx::Point(100, 100), size);
601 gfx::Rect source_rect(100, 100, 1, 1);
602 gfx::Vector2d dest_offset(1, 0);
603 resource_provider_->SetPixels(
604 id, image, offset_image_rect, source_rect, dest_offset);
606 uint8_t expected[16] = { 0, 1, 2, 3, 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3 };
607 GetResourcePixels(
608 resource_provider_.get(), context(), id, size, format, result);
609 EXPECT_EQ(0, memcmp(expected, result, pixel_size));
612 resource_provider_->DeleteResource(id);
615 TEST_P(ResourceProviderTest, TransferGLResources) {
616 if (GetParam() != ResourceProvider::GLTexture)
617 return;
618 gfx::Size size(1, 1);
619 ResourceFormat format = RGBA_8888;
620 size_t pixel_size = TextureSizeBytes(size, format);
621 ASSERT_EQ(4U, pixel_size);
623 ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource(
624 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
625 uint8_t data1[4] = { 1, 2, 3, 4 };
626 gfx::Rect rect(size);
627 child_resource_provider_->SetPixels(id1, data1, rect, rect, gfx::Vector2d());
629 ResourceProvider::ResourceId id2 = child_resource_provider_->CreateResource(
630 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
631 uint8_t data2[4] = { 5, 5, 5, 5 };
632 child_resource_provider_->SetPixels(id2, data2, rect, rect, gfx::Vector2d());
634 ResourceProvider::ResourceId id3 = child_resource_provider_->CreateResource(
635 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
636 child_resource_provider_->AcquireImageRasterBuffer(id3);
637 child_resource_provider_->ReleaseImageRasterBuffer(id3);
639 GLuint external_texture_id = child_context_->createExternalTexture();
640 child_context_->bindTexture(GL_TEXTURE_EXTERNAL_OES, external_texture_id);
642 gpu::Mailbox external_mailbox;
643 child_context_->genMailboxCHROMIUM(external_mailbox.name);
644 child_context_->produceTextureCHROMIUM(GL_TEXTURE_EXTERNAL_OES,
645 external_mailbox.name);
646 const GLuint external_sync_point = child_context_->insertSyncPoint();
647 ResourceProvider::ResourceId id4 =
648 child_resource_provider_->CreateResourceFromTextureMailbox(
649 TextureMailbox(
650 external_mailbox, GL_TEXTURE_EXTERNAL_OES, external_sync_point),
651 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback)));
653 ReturnedResourceArray returned_to_child;
654 int child_id =
655 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
657 // Transfer some resources to the parent.
658 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
659 resource_ids_to_transfer.push_back(id1);
660 resource_ids_to_transfer.push_back(id2);
661 resource_ids_to_transfer.push_back(id3);
662 resource_ids_to_transfer.push_back(id4);
663 TransferableResourceArray list;
664 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
665 &list);
666 ASSERT_EQ(4u, list.size());
667 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
668 EXPECT_NE(0u, list[1].mailbox_holder.sync_point);
669 EXPECT_EQ(list[0].mailbox_holder.sync_point,
670 list[1].mailbox_holder.sync_point);
671 EXPECT_NE(0u, list[2].mailbox_holder.sync_point);
672 EXPECT_EQ(list[0].mailbox_holder.sync_point,
673 list[2].mailbox_holder.sync_point);
674 EXPECT_EQ(external_sync_point, list[3].mailbox_holder.sync_point);
675 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
676 list[0].mailbox_holder.texture_target);
677 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
678 list[1].mailbox_holder.texture_target);
679 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
680 list[2].mailbox_holder.texture_target);
681 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_EXTERNAL_OES),
682 list[3].mailbox_holder.texture_target);
683 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
684 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
685 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
686 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id4));
687 resource_provider_->ReceiveFromChild(child_id, list);
688 EXPECT_NE(list[0].mailbox_holder.sync_point,
689 context3d_->last_waited_sync_point());
691 resource_provider_->WaitSyncPointIfNeeded(list[0].id);
692 ResourceProvider::ScopedReadLockGL lock(resource_provider_.get(),
693 list[0].id);
695 EXPECT_EQ(list[0].mailbox_holder.sync_point,
696 context3d_->last_waited_sync_point());
697 resource_provider_->DeclareUsedResourcesFromChild(child_id,
698 resource_ids_to_transfer);
701 EXPECT_EQ(4u, resource_provider_->num_resources());
702 ResourceProvider::ResourceIdMap resource_map =
703 resource_provider_->GetChildToParentMap(child_id);
704 ResourceProvider::ResourceId mapped_id1 = resource_map[id1];
705 ResourceProvider::ResourceId mapped_id2 = resource_map[id2];
706 ResourceProvider::ResourceId mapped_id3 = resource_map[id3];
707 ResourceProvider::ResourceId mapped_id4 = resource_map[id4];
708 EXPECT_NE(0u, mapped_id1);
709 EXPECT_NE(0u, mapped_id2);
710 EXPECT_NE(0u, mapped_id3);
711 EXPECT_NE(0u, mapped_id4);
712 EXPECT_FALSE(resource_provider_->InUseByConsumer(id1));
713 EXPECT_FALSE(resource_provider_->InUseByConsumer(id2));
714 EXPECT_FALSE(resource_provider_->InUseByConsumer(id3));
715 EXPECT_FALSE(resource_provider_->InUseByConsumer(id4));
717 uint8_t result[4] = { 0 };
718 GetResourcePixels(
719 resource_provider_.get(), context(), mapped_id1, size, format, result);
720 EXPECT_EQ(0, memcmp(data1, result, pixel_size));
722 GetResourcePixels(
723 resource_provider_.get(), context(), mapped_id2, size, format, result);
724 EXPECT_EQ(0, memcmp(data2, result, pixel_size));
727 // Check that transfering again the same resource from the child to the
728 // parent works.
729 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
730 resource_ids_to_transfer.push_back(id1);
731 resource_ids_to_transfer.push_back(id2);
732 resource_ids_to_transfer.push_back(id3);
733 TransferableResourceArray list;
734 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
735 &list);
736 EXPECT_EQ(3u, list.size());
737 EXPECT_EQ(id1, list[0].id);
738 EXPECT_EQ(id2, list[1].id);
739 EXPECT_EQ(id3, list[2].id);
740 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
741 list[0].mailbox_holder.texture_target);
742 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
743 list[1].mailbox_holder.texture_target);
744 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
745 list[2].mailbox_holder.texture_target);
746 ReturnedResourceArray returned;
747 TransferableResource::ReturnResources(list, &returned);
748 child_resource_provider_->ReceiveReturnsFromParent(returned);
749 // ids were exported twice, we returned them only once, they should still
750 // be in-use.
751 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
752 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
753 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
756 EXPECT_EQ(0u, returned_to_child.size());
758 // Transfer resources back from the parent to the child. Set no resources as
759 // being in use.
760 ResourceProvider::ResourceIdArray no_resources;
761 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
763 ASSERT_EQ(4u, returned_to_child.size());
764 EXPECT_NE(0u, returned_to_child[0].sync_point);
765 EXPECT_NE(0u, returned_to_child[1].sync_point);
766 EXPECT_NE(0u, returned_to_child[2].sync_point);
767 EXPECT_NE(0u, returned_to_child[3].sync_point);
768 EXPECT_FALSE(returned_to_child[0].lost);
769 EXPECT_FALSE(returned_to_child[1].lost);
770 EXPECT_FALSE(returned_to_child[2].lost);
771 EXPECT_FALSE(returned_to_child[3].lost);
772 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
773 returned_to_child.clear();
775 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id1));
776 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id2));
777 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id3));
778 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id4));
781 child_resource_provider_->WaitSyncPointIfNeeded(id1);
782 ResourceProvider::ScopedReadLockGL lock(child_resource_provider_.get(),
783 id1);
784 ASSERT_NE(0U, lock.texture_id());
785 child_context_->bindTexture(GL_TEXTURE_2D, lock.texture_id());
786 child_context_->GetPixels(size, format, result);
787 EXPECT_EQ(0, memcmp(data1, result, pixel_size));
790 child_resource_provider_->WaitSyncPointIfNeeded(id2);
791 ResourceProvider::ScopedReadLockGL lock(child_resource_provider_.get(),
792 id2);
793 ASSERT_NE(0U, lock.texture_id());
794 child_context_->bindTexture(GL_TEXTURE_2D, lock.texture_id());
795 child_context_->GetPixels(size, format, result);
796 EXPECT_EQ(0, memcmp(data2, result, pixel_size));
799 child_resource_provider_->WaitSyncPointIfNeeded(id3);
800 ResourceProvider::ScopedReadLockGL lock(child_resource_provider_.get(),
801 id3);
802 ASSERT_NE(0U, lock.texture_id());
803 child_context_->bindTexture(GL_TEXTURE_2D, lock.texture_id());
806 // Transfer resources to the parent again.
807 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
808 resource_ids_to_transfer.push_back(id1);
809 resource_ids_to_transfer.push_back(id2);
810 resource_ids_to_transfer.push_back(id3);
811 resource_ids_to_transfer.push_back(id4);
812 TransferableResourceArray list;
813 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
814 &list);
815 ASSERT_EQ(4u, list.size());
816 EXPECT_EQ(id1, list[0].id);
817 EXPECT_EQ(id2, list[1].id);
818 EXPECT_EQ(id3, list[2].id);
819 EXPECT_EQ(id4, list[3].id);
820 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
821 EXPECT_NE(0u, list[1].mailbox_holder.sync_point);
822 EXPECT_NE(0u, list[2].mailbox_holder.sync_point);
823 EXPECT_NE(0u, list[3].mailbox_holder.sync_point);
824 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
825 list[0].mailbox_holder.texture_target);
826 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
827 list[1].mailbox_holder.texture_target);
828 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
829 list[2].mailbox_holder.texture_target);
830 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_EXTERNAL_OES),
831 list[3].mailbox_holder.texture_target);
832 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
833 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
834 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
835 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id4));
836 resource_provider_->ReceiveFromChild(child_id, list);
837 resource_provider_->DeclareUsedResourcesFromChild(child_id,
838 resource_ids_to_transfer);
841 EXPECT_EQ(0u, returned_to_child.size());
843 EXPECT_EQ(4u, resource_provider_->num_resources());
844 resource_provider_->DestroyChild(child_id);
845 EXPECT_EQ(0u, resource_provider_->num_resources());
847 ASSERT_EQ(4u, returned_to_child.size());
848 EXPECT_NE(0u, returned_to_child[0].sync_point);
849 EXPECT_NE(0u, returned_to_child[1].sync_point);
850 EXPECT_NE(0u, returned_to_child[2].sync_point);
851 EXPECT_NE(0u, returned_to_child[3].sync_point);
852 EXPECT_FALSE(returned_to_child[0].lost);
853 EXPECT_FALSE(returned_to_child[1].lost);
854 EXPECT_FALSE(returned_to_child[2].lost);
855 EXPECT_FALSE(returned_to_child[3].lost);
858 TEST_P(ResourceProviderTest, ReadLockCountStopsReturnToChildOrDelete) {
859 if (GetParam() != ResourceProvider::GLTexture)
860 return;
861 gfx::Size size(1, 1);
862 ResourceFormat format = RGBA_8888;
864 ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource(
865 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
866 uint8_t data1[4] = {1, 2, 3, 4};
867 gfx::Rect rect(size);
868 child_resource_provider_->SetPixels(id1, data1, rect, rect, gfx::Vector2d());
870 ReturnedResourceArray returned_to_child;
871 int child_id =
872 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
874 // Transfer some resources to the parent.
875 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
876 resource_ids_to_transfer.push_back(id1);
877 TransferableResourceArray list;
878 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
879 &list);
880 ASSERT_EQ(1u, list.size());
881 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
883 resource_provider_->ReceiveFromChild(child_id, list);
885 resource_provider_->WaitSyncPointIfNeeded(list[0].id);
886 ResourceProvider::ScopedReadLockGL lock(resource_provider_.get(),
887 list[0].id);
889 resource_provider_->DeclareUsedResourcesFromChild(
890 child_id, ResourceProvider::ResourceIdArray());
891 EXPECT_EQ(0u, returned_to_child.size());
894 EXPECT_EQ(1u, returned_to_child.size());
895 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
898 child_resource_provider_->WaitSyncPointIfNeeded(id1);
899 ResourceProvider::ScopedReadLockGL lock(child_resource_provider_.get(),
900 id1);
901 child_resource_provider_->DeleteResource(id1);
902 EXPECT_EQ(1u, child_resource_provider_->num_resources());
903 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
906 EXPECT_EQ(0u, child_resource_provider_->num_resources());
907 resource_provider_->DestroyChild(child_id);
910 TEST_P(ResourceProviderTest, AllowOverlayTransfersToParent) {
911 // Overlays only supported on the GL path.
912 if (GetParam() != ResourceProvider::GLTexture)
913 return;
915 uint32 sync_point = 0;
916 TextureMailbox mailbox(gpu::Mailbox::Generate(), GL_TEXTURE_2D, sync_point);
917 mailbox.set_allow_overlay(true);
918 scoped_ptr<SingleReleaseCallbackImpl> release_callback =
919 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback));
920 ResourceProvider::ResourceId id1 =
921 child_resource_provider_->CreateResourceFromTextureMailbox(
922 mailbox, release_callback.Pass());
924 TextureMailbox mailbox2(gpu::Mailbox::Generate(), GL_TEXTURE_2D, sync_point);
925 mailbox2.set_allow_overlay(false);
926 scoped_ptr<SingleReleaseCallbackImpl> release_callback2 =
927 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback));
928 ResourceProvider::ResourceId id2 =
929 child_resource_provider_->CreateResourceFromTextureMailbox(
930 mailbox2, release_callback2.Pass());
932 ReturnedResourceArray returned_to_child;
933 int child_id =
934 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
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 TransferableResourceArray list;
941 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
942 &list);
943 ASSERT_EQ(2u, list.size());
944 resource_provider_->ReceiveFromChild(child_id, list);
945 EXPECT_TRUE(resource_provider_->AllowOverlay(list[0].id));
946 EXPECT_FALSE(resource_provider_->AllowOverlay(list[1].id));
948 resource_provider_->DeclareUsedResourcesFromChild(
949 child_id, ResourceProvider::ResourceIdArray());
951 EXPECT_EQ(2u, returned_to_child.size());
952 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
954 child_resource_provider_->DeleteResource(id1);
955 child_resource_provider_->DeleteResource(id2);
956 EXPECT_EQ(0u, child_resource_provider_->num_resources());
958 resource_provider_->DestroyChild(child_id);
961 TEST_P(ResourceProviderTest, TransferSoftwareResources) {
962 if (GetParam() != ResourceProvider::Bitmap)
963 return;
965 gfx::Size size(1, 1);
966 ResourceFormat format = RGBA_8888;
967 size_t pixel_size = TextureSizeBytes(size, format);
968 ASSERT_EQ(4U, pixel_size);
970 ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource(
971 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
972 uint8_t data1[4] = { 1, 2, 3, 4 };
973 gfx::Rect rect(size);
974 child_resource_provider_->SetPixels(id1, data1, rect, rect, gfx::Vector2d());
976 ResourceProvider::ResourceId id2 = child_resource_provider_->CreateResource(
977 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
978 uint8_t data2[4] = { 5, 5, 5, 5 };
979 child_resource_provider_->SetPixels(id2, data2, rect, rect, gfx::Vector2d());
981 ResourceProvider::ResourceId id3 = child_resource_provider_->CreateResource(
982 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
983 uint8_t data3[4] = { 6, 7, 8, 9 };
984 SkImageInfo info = SkImageInfo::MakeN32Premul(size.width(), size.height());
985 RasterBuffer* raster_buffer =
986 child_resource_provider_->AcquireImageRasterBuffer(id3);
987 skia::RefPtr<SkCanvas> canvas = raster_buffer->AcquireSkCanvas();
988 canvas->writePixels(info, data3, info.minRowBytes(), 0, 0);
989 raster_buffer->ReleaseSkCanvas(canvas);
990 canvas.clear();
991 child_resource_provider_->ReleaseImageRasterBuffer(id3);
993 scoped_ptr<base::SharedMemory> shared_memory(new base::SharedMemory());
994 shared_memory->CreateAndMapAnonymous(1);
995 base::SharedMemory* shared_memory_ptr = shared_memory.get();
996 ResourceProvider::ResourceId id4 =
997 child_resource_provider_->CreateResourceFromTextureMailbox(
998 TextureMailbox(shared_memory_ptr, gfx::Size(1, 1)),
999 SingleReleaseCallbackImpl::Create(base::Bind(
1000 &SharedMemoryReleaseCallback, base::Passed(&shared_memory))));
1002 ReturnedResourceArray returned_to_child;
1003 int child_id =
1004 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1006 // Transfer some resources to the parent.
1007 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1008 resource_ids_to_transfer.push_back(id1);
1009 resource_ids_to_transfer.push_back(id2);
1010 resource_ids_to_transfer.push_back(id3);
1011 resource_ids_to_transfer.push_back(id4);
1012 TransferableResourceArray list;
1013 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1014 &list);
1015 ASSERT_EQ(4u, list.size());
1016 EXPECT_EQ(0u, list[0].mailbox_holder.sync_point);
1017 EXPECT_EQ(0u, list[1].mailbox_holder.sync_point);
1018 EXPECT_EQ(0u, list[2].mailbox_holder.sync_point);
1019 EXPECT_EQ(0u, list[3].mailbox_holder.sync_point);
1020 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1021 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
1022 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
1023 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id4));
1024 resource_provider_->ReceiveFromChild(child_id, list);
1025 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1026 resource_ids_to_transfer);
1029 EXPECT_EQ(4u, resource_provider_->num_resources());
1030 ResourceProvider::ResourceIdMap resource_map =
1031 resource_provider_->GetChildToParentMap(child_id);
1032 ResourceProvider::ResourceId mapped_id1 = resource_map[id1];
1033 ResourceProvider::ResourceId mapped_id2 = resource_map[id2];
1034 ResourceProvider::ResourceId mapped_id3 = resource_map[id3];
1035 ResourceProvider::ResourceId mapped_id4 = resource_map[id4];
1036 EXPECT_NE(0u, mapped_id1);
1037 EXPECT_NE(0u, mapped_id2);
1038 EXPECT_NE(0u, mapped_id3);
1039 EXPECT_NE(0u, mapped_id4);
1040 EXPECT_FALSE(resource_provider_->InUseByConsumer(id1));
1041 EXPECT_FALSE(resource_provider_->InUseByConsumer(id2));
1042 EXPECT_FALSE(resource_provider_->InUseByConsumer(id3));
1043 EXPECT_FALSE(resource_provider_->InUseByConsumer(id4));
1045 uint8_t result[4] = { 0 };
1046 GetResourcePixels(
1047 resource_provider_.get(), context(), mapped_id1, size, format, result);
1048 EXPECT_EQ(0, memcmp(data1, result, pixel_size));
1050 GetResourcePixels(
1051 resource_provider_.get(), context(), mapped_id2, size, format, result);
1052 EXPECT_EQ(0, memcmp(data2, result, pixel_size));
1054 GetResourcePixels(
1055 resource_provider_.get(), context(), mapped_id3, size, format, result);
1056 EXPECT_EQ(0, memcmp(data3, result, pixel_size));
1059 // Check that transfering again the same resource from the child to the
1060 // parent works.
1061 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1062 resource_ids_to_transfer.push_back(id1);
1063 resource_ids_to_transfer.push_back(id2);
1064 resource_ids_to_transfer.push_back(id3);
1065 TransferableResourceArray list;
1066 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1067 &list);
1068 EXPECT_EQ(3u, list.size());
1069 EXPECT_EQ(id1, list[0].id);
1070 EXPECT_EQ(id2, list[1].id);
1071 EXPECT_EQ(id3, list[2].id);
1072 ReturnedResourceArray returned;
1073 TransferableResource::ReturnResources(list, &returned);
1074 child_resource_provider_->ReceiveReturnsFromParent(returned);
1075 // ids were exported twice, we returned them only once, they should still
1076 // be in-use.
1077 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1078 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
1079 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
1082 EXPECT_EQ(0u, returned_to_child.size());
1084 // Transfer resources back from the parent to the child. Set no resources as
1085 // being in use.
1086 ResourceProvider::ResourceIdArray no_resources;
1087 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
1089 ASSERT_EQ(4u, returned_to_child.size());
1090 EXPECT_EQ(0u, returned_to_child[0].sync_point);
1091 EXPECT_EQ(0u, returned_to_child[1].sync_point);
1092 EXPECT_EQ(0u, returned_to_child[2].sync_point);
1093 EXPECT_EQ(0u, returned_to_child[3].sync_point);
1094 std::set<ResourceProvider::ResourceId> expected_ids;
1095 expected_ids.insert(id1);
1096 expected_ids.insert(id2);
1097 expected_ids.insert(id3);
1098 expected_ids.insert(id4);
1099 std::set<ResourceProvider::ResourceId> returned_ids;
1100 for (unsigned i = 0; i < 4; i++)
1101 returned_ids.insert(returned_to_child[i].id);
1102 EXPECT_EQ(expected_ids, returned_ids);
1103 EXPECT_FALSE(returned_to_child[0].lost);
1104 EXPECT_FALSE(returned_to_child[1].lost);
1105 EXPECT_FALSE(returned_to_child[2].lost);
1106 EXPECT_FALSE(returned_to_child[3].lost);
1107 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
1108 returned_to_child.clear();
1110 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id1));
1111 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id2));
1112 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id3));
1113 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id4));
1116 ResourceProvider::ScopedReadLockSoftware lock(
1117 child_resource_provider_.get(), id1);
1118 const SkBitmap* sk_bitmap = lock.sk_bitmap();
1119 EXPECT_EQ(sk_bitmap->width(), size.width());
1120 EXPECT_EQ(sk_bitmap->height(), size.height());
1121 EXPECT_EQ(0, memcmp(data1, sk_bitmap->getPixels(), pixel_size));
1124 ResourceProvider::ScopedReadLockSoftware lock(
1125 child_resource_provider_.get(), id2);
1126 const SkBitmap* sk_bitmap = lock.sk_bitmap();
1127 EXPECT_EQ(sk_bitmap->width(), size.width());
1128 EXPECT_EQ(sk_bitmap->height(), size.height());
1129 EXPECT_EQ(0, memcmp(data2, sk_bitmap->getPixels(), pixel_size));
1132 ResourceProvider::ScopedReadLockSoftware lock(
1133 child_resource_provider_.get(), id3);
1134 const SkBitmap* sk_bitmap = lock.sk_bitmap();
1135 EXPECT_EQ(sk_bitmap->width(), size.width());
1136 EXPECT_EQ(sk_bitmap->height(), size.height());
1137 EXPECT_EQ(0, memcmp(data3, sk_bitmap->getPixels(), pixel_size));
1140 // Transfer resources to the parent again.
1141 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1142 resource_ids_to_transfer.push_back(id1);
1143 resource_ids_to_transfer.push_back(id2);
1144 resource_ids_to_transfer.push_back(id3);
1145 resource_ids_to_transfer.push_back(id4);
1146 TransferableResourceArray list;
1147 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1148 &list);
1149 ASSERT_EQ(4u, list.size());
1150 EXPECT_EQ(id1, list[0].id);
1151 EXPECT_EQ(id2, list[1].id);
1152 EXPECT_EQ(id3, list[2].id);
1153 EXPECT_EQ(id4, list[3].id);
1154 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1155 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
1156 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id3));
1157 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id4));
1158 resource_provider_->ReceiveFromChild(child_id, list);
1159 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1160 resource_ids_to_transfer);
1163 EXPECT_EQ(0u, returned_to_child.size());
1165 EXPECT_EQ(4u, resource_provider_->num_resources());
1166 resource_provider_->DestroyChild(child_id);
1167 EXPECT_EQ(0u, resource_provider_->num_resources());
1169 ASSERT_EQ(4u, returned_to_child.size());
1170 EXPECT_EQ(0u, returned_to_child[0].sync_point);
1171 EXPECT_EQ(0u, returned_to_child[1].sync_point);
1172 EXPECT_EQ(0u, returned_to_child[2].sync_point);
1173 EXPECT_EQ(0u, returned_to_child[3].sync_point);
1174 std::set<ResourceProvider::ResourceId> expected_ids;
1175 expected_ids.insert(id1);
1176 expected_ids.insert(id2);
1177 expected_ids.insert(id3);
1178 expected_ids.insert(id4);
1179 std::set<ResourceProvider::ResourceId> returned_ids;
1180 for (unsigned i = 0; i < 4; i++)
1181 returned_ids.insert(returned_to_child[i].id);
1182 EXPECT_EQ(expected_ids, returned_ids);
1183 EXPECT_FALSE(returned_to_child[0].lost);
1184 EXPECT_FALSE(returned_to_child[1].lost);
1185 EXPECT_FALSE(returned_to_child[2].lost);
1186 EXPECT_FALSE(returned_to_child[3].lost);
1189 TEST_P(ResourceProviderTest, TransferGLToSoftware) {
1190 if (GetParam() != ResourceProvider::Bitmap)
1191 return;
1193 scoped_ptr<ResourceProviderContext> child_context_owned(
1194 ResourceProviderContext::Create(shared_data_.get()));
1196 FakeOutputSurfaceClient child_output_surface_client;
1197 scoped_ptr<OutputSurface> child_output_surface(FakeOutputSurface::Create3d(
1198 child_context_owned.PassAs<TestWebGraphicsContext3D>()));
1199 CHECK(child_output_surface->BindToClient(&child_output_surface_client));
1201 scoped_ptr<ResourceProvider> child_resource_provider(
1202 ResourceProvider::Create(child_output_surface.get(),
1203 shared_bitmap_manager_.get(),
1204 NULL,
1206 false,
1208 false));
1210 gfx::Size size(1, 1);
1211 ResourceFormat format = RGBA_8888;
1212 size_t pixel_size = TextureSizeBytes(size, format);
1213 ASSERT_EQ(4U, pixel_size);
1215 ResourceProvider::ResourceId id1 = child_resource_provider->CreateResource(
1216 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
1217 uint8_t data1[4] = { 1, 2, 3, 4 };
1218 gfx::Rect rect(size);
1219 child_resource_provider->SetPixels(id1, data1, rect, rect, gfx::Vector2d());
1221 ReturnedResourceArray returned_to_child;
1222 int child_id =
1223 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1225 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1226 resource_ids_to_transfer.push_back(id1);
1227 TransferableResourceArray list;
1228 child_resource_provider->PrepareSendToParent(resource_ids_to_transfer,
1229 &list);
1230 ASSERT_EQ(1u, list.size());
1231 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
1232 EXPECT_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
1233 list[0].mailbox_holder.texture_target);
1234 EXPECT_TRUE(child_resource_provider->InUseByConsumer(id1));
1235 resource_provider_->ReceiveFromChild(child_id, list);
1238 EXPECT_EQ(0u, resource_provider_->num_resources());
1239 ASSERT_EQ(1u, returned_to_child.size());
1240 EXPECT_EQ(returned_to_child[0].id, id1);
1241 ResourceProvider::ResourceIdMap resource_map =
1242 resource_provider_->GetChildToParentMap(child_id);
1243 ResourceProvider::ResourceId mapped_id1 = resource_map[id1];
1244 EXPECT_EQ(0u, mapped_id1);
1246 resource_provider_->DestroyChild(child_id);
1247 EXPECT_EQ(0u, resource_provider_->num_resources());
1249 ASSERT_EQ(1u, returned_to_child.size());
1250 EXPECT_FALSE(returned_to_child[0].lost);
1253 TEST_P(ResourceProviderTest, TransferInvalidSoftware) {
1254 if (GetParam() != ResourceProvider::Bitmap)
1255 return;
1257 gfx::Size size(1, 1);
1258 ResourceFormat format = RGBA_8888;
1259 size_t pixel_size = TextureSizeBytes(size, format);
1260 ASSERT_EQ(4U, pixel_size);
1262 ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource(
1263 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
1264 uint8_t data1[4] = { 1, 2, 3, 4 };
1265 gfx::Rect rect(size);
1266 child_resource_provider_->SetPixels(id1, data1, rect, rect, gfx::Vector2d());
1268 ReturnedResourceArray returned_to_child;
1269 int child_id =
1270 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1272 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1273 resource_ids_to_transfer.push_back(id1);
1274 TransferableResourceArray list;
1275 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1276 &list);
1277 ASSERT_EQ(1u, list.size());
1278 // Make invalid.
1279 list[0].mailbox_holder.mailbox.name[1] = 5;
1280 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1281 resource_provider_->ReceiveFromChild(child_id, list);
1284 EXPECT_EQ(1u, resource_provider_->num_resources());
1285 EXPECT_EQ(0u, returned_to_child.size());
1287 ResourceProvider::ResourceIdMap resource_map =
1288 resource_provider_->GetChildToParentMap(child_id);
1289 ResourceProvider::ResourceId mapped_id1 = resource_map[id1];
1290 EXPECT_NE(0u, mapped_id1);
1292 ResourceProvider::ScopedReadLockSoftware lock(resource_provider_.get(),
1293 mapped_id1);
1294 EXPECT_FALSE(lock.valid());
1297 resource_provider_->DestroyChild(child_id);
1298 EXPECT_EQ(0u, resource_provider_->num_resources());
1300 ASSERT_EQ(1u, returned_to_child.size());
1301 EXPECT_FALSE(returned_to_child[0].lost);
1304 TEST_P(ResourceProviderTest, DeleteExportedResources) {
1305 gfx::Size size(1, 1);
1306 ResourceFormat format = RGBA_8888;
1307 size_t pixel_size = TextureSizeBytes(size, format);
1308 ASSERT_EQ(4U, pixel_size);
1310 ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource(
1311 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
1312 uint8_t data1[4] = { 1, 2, 3, 4 };
1313 gfx::Rect rect(size);
1314 child_resource_provider_->SetPixels(id1, data1, rect, rect, gfx::Vector2d());
1316 ResourceProvider::ResourceId id2 = child_resource_provider_->CreateResource(
1317 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
1318 uint8_t data2[4] = {5, 5, 5, 5};
1319 child_resource_provider_->SetPixels(id2, data2, rect, rect, gfx::Vector2d());
1321 ReturnedResourceArray returned_to_child;
1322 int child_id =
1323 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1325 // Transfer some resources to the parent.
1326 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1327 resource_ids_to_transfer.push_back(id1);
1328 resource_ids_to_transfer.push_back(id2);
1329 TransferableResourceArray list;
1330 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1331 &list);
1332 ASSERT_EQ(2u, list.size());
1333 if (GetParam() == ResourceProvider::GLTexture) {
1334 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
1335 EXPECT_NE(0u, list[1].mailbox_holder.sync_point);
1337 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1338 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
1339 resource_provider_->ReceiveFromChild(child_id, list);
1340 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1341 resource_ids_to_transfer);
1344 EXPECT_EQ(2u, resource_provider_->num_resources());
1345 ResourceProvider::ResourceIdMap resource_map =
1346 resource_provider_->GetChildToParentMap(child_id);
1347 ResourceProvider::ResourceId mapped_id1 = resource_map[id1];
1348 ResourceProvider::ResourceId mapped_id2 = resource_map[id2];
1349 EXPECT_NE(0u, mapped_id1);
1350 EXPECT_NE(0u, mapped_id2);
1351 EXPECT_FALSE(resource_provider_->InUseByConsumer(id1));
1352 EXPECT_FALSE(resource_provider_->InUseByConsumer(id2));
1355 // The parent transfers the resources to the grandparent.
1356 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1357 resource_ids_to_transfer.push_back(mapped_id1);
1358 resource_ids_to_transfer.push_back(mapped_id2);
1359 TransferableResourceArray list;
1360 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
1362 ASSERT_EQ(2u, list.size());
1363 if (GetParam() == ResourceProvider::GLTexture) {
1364 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
1365 EXPECT_NE(0u, list[1].mailbox_holder.sync_point);
1367 EXPECT_TRUE(resource_provider_->InUseByConsumer(id1));
1368 EXPECT_TRUE(resource_provider_->InUseByConsumer(id2));
1370 // Release the resource in the parent. Set no resources as being in use. The
1371 // resources are exported so that can't be transferred back yet.
1372 ResourceProvider::ResourceIdArray no_resources;
1373 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
1375 EXPECT_EQ(0u, returned_to_child.size());
1376 EXPECT_EQ(2u, resource_provider_->num_resources());
1378 // Return the resources from the grandparent to the parent. They should be
1379 // returned to the child then.
1380 EXPECT_EQ(2u, list.size());
1381 EXPECT_EQ(mapped_id1, list[0].id);
1382 EXPECT_EQ(mapped_id2, list[1].id);
1383 ReturnedResourceArray returned;
1384 TransferableResource::ReturnResources(list, &returned);
1385 resource_provider_->ReceiveReturnsFromParent(returned);
1387 EXPECT_EQ(0u, resource_provider_->num_resources());
1388 ASSERT_EQ(2u, returned_to_child.size());
1389 if (GetParam() == ResourceProvider::GLTexture) {
1390 EXPECT_NE(0u, returned_to_child[0].sync_point);
1391 EXPECT_NE(0u, returned_to_child[1].sync_point);
1393 EXPECT_FALSE(returned_to_child[0].lost);
1394 EXPECT_FALSE(returned_to_child[1].lost);
1398 TEST_P(ResourceProviderTest, DestroyChildWithExportedResources) {
1399 gfx::Size size(1, 1);
1400 ResourceFormat format = RGBA_8888;
1401 size_t pixel_size = TextureSizeBytes(size, format);
1402 ASSERT_EQ(4U, pixel_size);
1404 ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource(
1405 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
1406 uint8_t data1[4] = {1, 2, 3, 4};
1407 gfx::Rect rect(size);
1408 child_resource_provider_->SetPixels(id1, data1, rect, rect, gfx::Vector2d());
1410 ResourceProvider::ResourceId id2 = child_resource_provider_->CreateResource(
1411 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
1412 uint8_t data2[4] = {5, 5, 5, 5};
1413 child_resource_provider_->SetPixels(id2, data2, rect, rect, gfx::Vector2d());
1415 ReturnedResourceArray returned_to_child;
1416 int child_id =
1417 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1419 // Transfer some resources to the parent.
1420 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1421 resource_ids_to_transfer.push_back(id1);
1422 resource_ids_to_transfer.push_back(id2);
1423 TransferableResourceArray list;
1424 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1425 &list);
1426 ASSERT_EQ(2u, list.size());
1427 if (GetParam() == ResourceProvider::GLTexture) {
1428 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
1429 EXPECT_NE(0u, list[1].mailbox_holder.sync_point);
1431 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
1432 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
1433 resource_provider_->ReceiveFromChild(child_id, list);
1434 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1435 resource_ids_to_transfer);
1438 EXPECT_EQ(2u, resource_provider_->num_resources());
1439 ResourceProvider::ResourceIdMap resource_map =
1440 resource_provider_->GetChildToParentMap(child_id);
1441 ResourceProvider::ResourceId mapped_id1 = resource_map[id1];
1442 ResourceProvider::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::GLTexture) {
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::ResourceIdArray no_resources;
1467 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
1469 // Destroy the child, the resources should not be returned yet.
1470 EXPECT_EQ(0u, returned_to_child.size());
1471 EXPECT_EQ(2u, resource_provider_->num_resources());
1473 resource_provider_->DestroyChild(child_id);
1475 EXPECT_EQ(2u, resource_provider_->num_resources());
1476 ASSERT_EQ(0u, returned_to_child.size());
1478 // Return a resource from the grandparent, it should be returned at this
1479 // point.
1480 EXPECT_EQ(2u, list.size());
1481 EXPECT_EQ(mapped_id1, list[0].id);
1482 EXPECT_EQ(mapped_id2, list[1].id);
1483 TransferableResourceArray return_list;
1484 return_list.push_back(list[1]);
1485 list.pop_back();
1486 ReturnedResourceArray returned;
1487 TransferableResource::ReturnResources(return_list, &returned);
1488 resource_provider_->ReceiveReturnsFromParent(returned);
1490 EXPECT_EQ(1u, resource_provider_->num_resources());
1491 ASSERT_EQ(1u, returned_to_child.size());
1492 if (GetParam() == ResourceProvider::GLTexture) {
1493 EXPECT_NE(0u, returned_to_child[0].sync_point);
1495 EXPECT_FALSE(returned_to_child[0].lost);
1496 returned_to_child.clear();
1498 // Destroy the parent resource provider. The resource that's left should be
1499 // lost at this point, and returned.
1500 resource_provider_.reset();
1501 ASSERT_EQ(1u, returned_to_child.size());
1502 if (GetParam() == ResourceProvider::GLTexture) {
1503 EXPECT_NE(0u, returned_to_child[0].sync_point);
1505 EXPECT_TRUE(returned_to_child[0].lost);
1509 TEST_P(ResourceProviderTest, DeleteTransferredResources) {
1510 gfx::Size size(1, 1);
1511 ResourceFormat format = RGBA_8888;
1512 size_t pixel_size = TextureSizeBytes(size, format);
1513 ASSERT_EQ(4U, pixel_size);
1515 ResourceProvider::ResourceId id = child_resource_provider_->CreateResource(
1516 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
1517 uint8_t data[4] = { 1, 2, 3, 4 };
1518 gfx::Rect rect(size);
1519 child_resource_provider_->SetPixels(id, data, rect, rect, gfx::Vector2d());
1521 ReturnedResourceArray returned_to_child;
1522 int child_id =
1523 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1525 // Transfer some resource to the parent.
1526 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1527 resource_ids_to_transfer.push_back(id);
1528 TransferableResourceArray list;
1529 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1530 &list);
1531 ASSERT_EQ(1u, list.size());
1532 if (GetParam() == ResourceProvider::GLTexture)
1533 EXPECT_NE(0u, list[0].mailbox_holder.sync_point);
1534 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id));
1535 resource_provider_->ReceiveFromChild(child_id, list);
1536 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1537 resource_ids_to_transfer);
1540 // Delete textures in the child, while they are transfered.
1541 child_resource_provider_->DeleteResource(id);
1542 EXPECT_EQ(1u, child_resource_provider_->num_resources());
1544 EXPECT_EQ(0u, returned_to_child.size());
1546 // Transfer resources back from the parent to the child. Set no resources as
1547 // being in use.
1548 ResourceProvider::ResourceIdArray no_resources;
1549 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
1551 ASSERT_EQ(1u, returned_to_child.size());
1552 if (GetParam() == ResourceProvider::GLTexture)
1553 EXPECT_NE(0u, returned_to_child[0].sync_point);
1554 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
1556 EXPECT_EQ(0u, child_resource_provider_->num_resources());
1559 TEST_P(ResourceProviderTest, UnuseTransferredResources) {
1560 gfx::Size size(1, 1);
1561 ResourceFormat format = RGBA_8888;
1562 size_t pixel_size = TextureSizeBytes(size, format);
1563 ASSERT_EQ(4U, pixel_size);
1565 ResourceProvider::ResourceId id = child_resource_provider_->CreateResource(
1566 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
1567 uint8_t data[4] = {1, 2, 3, 4};
1568 gfx::Rect rect(size);
1569 child_resource_provider_->SetPixels(id, data, rect, rect, gfx::Vector2d());
1571 ReturnedResourceArray returned_to_child;
1572 int child_id =
1573 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
1574 const ResourceProvider::ResourceIdMap& map =
1575 resource_provider_->GetChildToParentMap(child_id);
1577 // Transfer some resource to the parent.
1578 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1579 resource_ids_to_transfer.push_back(id);
1580 TransferableResourceArray list;
1581 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1582 &list);
1583 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id));
1584 resource_provider_->ReceiveFromChild(child_id, list);
1585 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1586 resource_ids_to_transfer);
1588 TransferableResourceArray sent_to_top_level;
1590 // Parent transfers to top-level.
1591 ASSERT_TRUE(map.find(id) != map.end());
1592 ResourceProvider::ResourceId parent_id = map.find(id)->second;
1593 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1594 resource_ids_to_transfer.push_back(parent_id);
1595 resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1596 &sent_to_top_level);
1597 EXPECT_TRUE(resource_provider_->InUseByConsumer(parent_id));
1600 // Stop using resource.
1601 ResourceProvider::ResourceIdArray empty;
1602 resource_provider_->DeclareUsedResourcesFromChild(child_id, empty);
1603 // Resource is not yet returned to the child, since it's in use by the
1604 // top-level.
1605 EXPECT_TRUE(returned_to_child.empty());
1608 // Send the resource to the parent again.
1609 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1610 resource_ids_to_transfer.push_back(id);
1611 TransferableResourceArray list;
1612 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1613 &list);
1614 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id));
1615 resource_provider_->ReceiveFromChild(child_id, list);
1616 resource_provider_->DeclareUsedResourcesFromChild(child_id,
1617 resource_ids_to_transfer);
1620 // Receive returns back from top-level.
1621 ReturnedResourceArray returned;
1622 TransferableResource::ReturnResources(sent_to_top_level, &returned);
1623 resource_provider_->ReceiveReturnsFromParent(returned);
1624 // Resource is still not yet returned to the child, since it's declared used
1625 // in the parent.
1626 EXPECT_TRUE(returned_to_child.empty());
1627 ASSERT_TRUE(map.find(id) != map.end());
1628 ResourceProvider::ResourceId parent_id = map.find(id)->second;
1629 EXPECT_FALSE(resource_provider_->InUseByConsumer(parent_id));
1632 sent_to_top_level.clear();
1633 // Parent transfers again to top-level.
1634 ASSERT_TRUE(map.find(id) != map.end());
1635 ResourceProvider::ResourceId parent_id = map.find(id)->second;
1636 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1637 resource_ids_to_transfer.push_back(parent_id);
1638 resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
1639 &sent_to_top_level);
1640 EXPECT_TRUE(resource_provider_->InUseByConsumer(parent_id));
1643 // Receive returns back from top-level.
1644 ReturnedResourceArray returned;
1645 TransferableResource::ReturnResources(sent_to_top_level, &returned);
1646 resource_provider_->ReceiveReturnsFromParent(returned);
1647 // Resource is still not yet returned to the child, since it's still
1648 // declared used in the parent.
1649 EXPECT_TRUE(returned_to_child.empty());
1650 ASSERT_TRUE(map.find(id) != map.end());
1651 ResourceProvider::ResourceId parent_id = map.find(id)->second;
1652 EXPECT_FALSE(resource_provider_->InUseByConsumer(parent_id));
1655 // Stop using resource.
1656 ResourceProvider::ResourceIdArray empty;
1657 resource_provider_->DeclareUsedResourcesFromChild(child_id, empty);
1658 // Resource should have been returned to the child, since it's no longer in
1659 // use by the top-level.
1660 ASSERT_EQ(1u, returned_to_child.size());
1661 EXPECT_EQ(id, returned_to_child[0].id);
1662 EXPECT_EQ(2, returned_to_child[0].count);
1663 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
1664 returned_to_child.clear();
1665 EXPECT_FALSE(child_resource_provider_->InUseByConsumer(id));
1669 class ResourceProviderTestTextureFilters : public ResourceProviderTest {
1670 public:
1671 static void RunTest(GLenum child_filter, GLenum parent_filter) {
1672 scoped_ptr<TextureStateTrackingContext> child_context_owned(
1673 new TextureStateTrackingContext);
1674 TextureStateTrackingContext* child_context = child_context_owned.get();
1676 FakeOutputSurfaceClient child_output_surface_client;
1677 scoped_ptr<OutputSurface> child_output_surface(FakeOutputSurface::Create3d(
1678 child_context_owned.PassAs<TestWebGraphicsContext3D>()));
1679 CHECK(child_output_surface->BindToClient(&child_output_surface_client));
1680 scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
1681 new TestSharedBitmapManager());
1683 scoped_ptr<ResourceProvider> child_resource_provider(
1684 ResourceProvider::Create(child_output_surface.get(),
1685 shared_bitmap_manager.get(),
1686 NULL,
1688 false,
1690 false));
1692 scoped_ptr<TextureStateTrackingContext> parent_context_owned(
1693 new TextureStateTrackingContext);
1694 TextureStateTrackingContext* parent_context = parent_context_owned.get();
1696 FakeOutputSurfaceClient parent_output_surface_client;
1697 scoped_ptr<OutputSurface> parent_output_surface(FakeOutputSurface::Create3d(
1698 parent_context_owned.PassAs<TestWebGraphicsContext3D>()));
1699 CHECK(parent_output_surface->BindToClient(&parent_output_surface_client));
1701 scoped_ptr<ResourceProvider> parent_resource_provider(
1702 ResourceProvider::Create(parent_output_surface.get(),
1703 shared_bitmap_manager.get(),
1704 NULL,
1706 false,
1708 false));
1710 gfx::Size size(1, 1);
1711 ResourceFormat format = RGBA_8888;
1712 int child_texture_id = 1;
1713 int parent_texture_id = 2;
1715 size_t pixel_size = TextureSizeBytes(size, format);
1716 ASSERT_EQ(4U, pixel_size);
1718 ResourceProvider::ResourceId id = child_resource_provider->CreateResource(
1719 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
1721 // The new texture is created with GL_LINEAR.
1722 EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, child_texture_id))
1723 .Times(2); // Once to create and once to allocate.
1724 EXPECT_CALL(*child_context,
1725 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
1726 EXPECT_CALL(*child_context,
1727 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
1728 EXPECT_CALL(
1729 *child_context,
1730 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
1731 EXPECT_CALL(
1732 *child_context,
1733 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
1734 EXPECT_CALL(*child_context,
1735 texParameteri(GL_TEXTURE_2D,
1736 GL_TEXTURE_POOL_CHROMIUM,
1737 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM));
1738 child_resource_provider->AllocateForTesting(id);
1739 Mock::VerifyAndClearExpectations(child_context);
1741 uint8_t data[4] = { 1, 2, 3, 4 };
1742 gfx::Rect rect(size);
1744 EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, child_texture_id));
1745 child_resource_provider->SetPixels(id, data, rect, rect, gfx::Vector2d());
1746 Mock::VerifyAndClearExpectations(child_context);
1748 // The texture is set to |child_filter| in the child.
1749 EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, child_texture_id));
1750 if (child_filter != GL_LINEAR) {
1751 EXPECT_CALL(
1752 *child_context,
1753 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, child_filter));
1754 EXPECT_CALL(
1755 *child_context,
1756 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, child_filter));
1758 SetResourceFilter(child_resource_provider.get(), id, child_filter);
1759 Mock::VerifyAndClearExpectations(child_context);
1761 ReturnedResourceArray returned_to_child;
1762 int child_id = parent_resource_provider->CreateChild(
1763 GetReturnCallback(&returned_to_child));
1765 // Transfer some resource to the parent.
1766 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1767 resource_ids_to_transfer.push_back(id);
1768 TransferableResourceArray list;
1770 EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, child_texture_id));
1771 EXPECT_CALL(*child_context,
1772 produceTextureCHROMIUM(GL_TEXTURE_2D, _));
1773 EXPECT_CALL(*child_context, insertSyncPoint());
1774 child_resource_provider->PrepareSendToParent(resource_ids_to_transfer,
1775 &list);
1776 Mock::VerifyAndClearExpectations(child_context);
1778 ASSERT_EQ(1u, list.size());
1779 EXPECT_EQ(static_cast<unsigned>(child_filter), list[0].filter);
1781 EXPECT_CALL(*parent_context,
1782 bindTexture(GL_TEXTURE_2D, parent_texture_id));
1783 EXPECT_CALL(*parent_context, consumeTextureCHROMIUM(GL_TEXTURE_2D, _));
1784 parent_resource_provider->ReceiveFromChild(child_id, list);
1786 parent_resource_provider->WaitSyncPointIfNeeded(list[0].id);
1787 ResourceProvider::ScopedReadLockGL lock(parent_resource_provider.get(),
1788 list[0].id);
1790 Mock::VerifyAndClearExpectations(parent_context);
1792 parent_resource_provider->DeclareUsedResourcesFromChild(
1793 child_id, resource_ids_to_transfer);
1794 Mock::VerifyAndClearExpectations(parent_context);
1796 ResourceProvider::ResourceIdMap resource_map =
1797 parent_resource_provider->GetChildToParentMap(child_id);
1798 ResourceProvider::ResourceId mapped_id = resource_map[id];
1799 EXPECT_NE(0u, mapped_id);
1801 // The texture is set to |parent_filter| in the parent.
1802 EXPECT_CALL(*parent_context, bindTexture(GL_TEXTURE_2D, parent_texture_id));
1803 EXPECT_CALL(
1804 *parent_context,
1805 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, parent_filter));
1806 EXPECT_CALL(
1807 *parent_context,
1808 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, parent_filter));
1809 SetResourceFilter(parent_resource_provider.get(), mapped_id, parent_filter);
1810 Mock::VerifyAndClearExpectations(parent_context);
1812 // The texture should be reset to |child_filter| in the parent when it is
1813 // returned, since that is how it was received.
1814 EXPECT_CALL(*parent_context, bindTexture(GL_TEXTURE_2D, parent_texture_id));
1815 EXPECT_CALL(
1816 *parent_context,
1817 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, child_filter));
1818 EXPECT_CALL(
1819 *parent_context,
1820 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, child_filter));
1823 EXPECT_EQ(0u, returned_to_child.size());
1825 // Transfer resources back from the parent to the child. Set no resources
1826 // as being in use.
1827 ResourceProvider::ResourceIdArray no_resources;
1828 EXPECT_CALL(*parent_context, insertSyncPoint());
1829 parent_resource_provider->DeclareUsedResourcesFromChild(child_id,
1830 no_resources);
1831 Mock::VerifyAndClearExpectations(parent_context);
1833 ASSERT_EQ(1u, returned_to_child.size());
1834 child_resource_provider->ReceiveReturnsFromParent(returned_to_child);
1837 // The child remembers the texture filter is set to |child_filter|.
1838 EXPECT_CALL(*child_context, bindTexture(GL_TEXTURE_2D, child_texture_id));
1839 SetResourceFilter(child_resource_provider.get(), id, child_filter);
1840 Mock::VerifyAndClearExpectations(child_context);
1844 TEST_P(ResourceProviderTest, TextureFilters_ChildNearestParentLinear) {
1845 if (GetParam() != ResourceProvider::GLTexture)
1846 return;
1847 ResourceProviderTestTextureFilters::RunTest(GL_NEAREST, GL_LINEAR);
1850 TEST_P(ResourceProviderTest, TextureFilters_ChildLinearParentNearest) {
1851 if (GetParam() != ResourceProvider::GLTexture)
1852 return;
1853 ResourceProviderTestTextureFilters::RunTest(GL_LINEAR, GL_NEAREST);
1856 TEST_P(ResourceProviderTest, TransferMailboxResources) {
1857 // Other mailbox transfers tested elsewhere.
1858 if (GetParam() != ResourceProvider::GLTexture)
1859 return;
1860 unsigned texture = context()->createTexture();
1861 context()->bindTexture(GL_TEXTURE_2D, texture);
1862 uint8_t data[4] = { 1, 2, 3, 4 };
1863 context()->texImage2D(
1864 GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &data);
1865 gpu::Mailbox mailbox;
1866 context()->genMailboxCHROMIUM(mailbox.name);
1867 context()->produceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
1868 uint32 sync_point = context()->insertSyncPoint();
1870 // All the logic below assumes that the sync points are all positive.
1871 EXPECT_LT(0u, sync_point);
1873 uint32 release_sync_point = 0;
1874 bool lost_resource = false;
1875 BlockingTaskRunner* main_thread_task_runner = NULL;
1876 ReleaseCallbackImpl callback = base::Bind(ReleaseCallback,
1877 &release_sync_point,
1878 &lost_resource,
1879 &main_thread_task_runner);
1880 ResourceProvider::ResourceId resource =
1881 resource_provider_->CreateResourceFromTextureMailbox(
1882 TextureMailbox(mailbox, GL_TEXTURE_2D, sync_point),
1883 SingleReleaseCallbackImpl::Create(callback));
1884 EXPECT_EQ(1u, context()->NumTextures());
1885 EXPECT_EQ(0u, release_sync_point);
1887 // Transfer the resource, expect the sync points to be consistent.
1888 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1889 resource_ids_to_transfer.push_back(resource);
1890 TransferableResourceArray list;
1891 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
1892 ASSERT_EQ(1u, list.size());
1893 EXPECT_LE(sync_point, list[0].mailbox_holder.sync_point);
1894 EXPECT_EQ(0,
1895 memcmp(mailbox.name,
1896 list[0].mailbox_holder.mailbox.name,
1897 sizeof(mailbox.name)));
1898 EXPECT_EQ(0u, release_sync_point);
1900 context()->waitSyncPoint(list[0].mailbox_holder.sync_point);
1901 unsigned other_texture = context()->createTexture();
1902 context()->bindTexture(GL_TEXTURE_2D, other_texture);
1903 context()->consumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
1904 uint8_t test_data[4] = { 0 };
1905 context()->GetPixels(
1906 gfx::Size(1, 1), RGBA_8888, test_data);
1907 EXPECT_EQ(0, memcmp(data, test_data, sizeof(data)));
1908 context()->produceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
1909 context()->deleteTexture(other_texture);
1910 list[0].mailbox_holder.sync_point = context()->insertSyncPoint();
1911 EXPECT_LT(0u, list[0].mailbox_holder.sync_point);
1913 // Receive the resource, then delete it, expect the sync points to be
1914 // consistent.
1915 ReturnedResourceArray returned;
1916 TransferableResource::ReturnResources(list, &returned);
1917 resource_provider_->ReceiveReturnsFromParent(returned);
1918 EXPECT_EQ(1u, context()->NumTextures());
1919 EXPECT_EQ(0u, release_sync_point);
1921 resource_provider_->DeleteResource(resource);
1922 EXPECT_LE(list[0].mailbox_holder.sync_point, release_sync_point);
1923 EXPECT_FALSE(lost_resource);
1924 EXPECT_EQ(main_thread_task_runner_.get(), main_thread_task_runner);
1927 // We're going to do the same thing as above, but testing the case where we
1928 // delete the resource before we receive it back.
1929 sync_point = release_sync_point;
1930 EXPECT_LT(0u, sync_point);
1931 release_sync_point = 0;
1932 resource = resource_provider_->CreateResourceFromTextureMailbox(
1933 TextureMailbox(mailbox, GL_TEXTURE_2D, sync_point),
1934 SingleReleaseCallbackImpl::Create(callback));
1935 EXPECT_EQ(1u, context()->NumTextures());
1936 EXPECT_EQ(0u, release_sync_point);
1938 // Transfer the resource, expect the sync points to be consistent.
1939 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
1940 resource_ids_to_transfer.push_back(resource);
1941 TransferableResourceArray list;
1942 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
1943 ASSERT_EQ(1u, list.size());
1944 EXPECT_LE(sync_point, list[0].mailbox_holder.sync_point);
1945 EXPECT_EQ(0,
1946 memcmp(mailbox.name,
1947 list[0].mailbox_holder.mailbox.name,
1948 sizeof(mailbox.name)));
1949 EXPECT_EQ(0u, release_sync_point);
1951 context()->waitSyncPoint(list[0].mailbox_holder.sync_point);
1952 unsigned other_texture = context()->createTexture();
1953 context()->bindTexture(GL_TEXTURE_2D, other_texture);
1954 context()->consumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
1955 uint8_t test_data[4] = { 0 };
1956 context()->GetPixels(
1957 gfx::Size(1, 1), RGBA_8888, test_data);
1958 EXPECT_EQ(0, memcmp(data, test_data, sizeof(data)));
1959 context()->produceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
1960 context()->deleteTexture(other_texture);
1961 list[0].mailbox_holder.sync_point = context()->insertSyncPoint();
1962 EXPECT_LT(0u, list[0].mailbox_holder.sync_point);
1964 // Delete the resource, which shouldn't do anything.
1965 resource_provider_->DeleteResource(resource);
1966 EXPECT_EQ(1u, context()->NumTextures());
1967 EXPECT_EQ(0u, release_sync_point);
1969 // Then receive the resource which should release the mailbox, expect the
1970 // sync points to be consistent.
1971 ReturnedResourceArray returned;
1972 TransferableResource::ReturnResources(list, &returned);
1973 resource_provider_->ReceiveReturnsFromParent(returned);
1974 EXPECT_LE(list[0].mailbox_holder.sync_point, release_sync_point);
1975 EXPECT_FALSE(lost_resource);
1976 EXPECT_EQ(main_thread_task_runner_.get(), main_thread_task_runner);
1979 context()->waitSyncPoint(release_sync_point);
1980 context()->bindTexture(GL_TEXTURE_2D, texture);
1981 context()->consumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
1982 context()->deleteTexture(texture);
1985 TEST_P(ResourceProviderTest, LostResourceInParent) {
1986 gfx::Size size(1, 1);
1987 ResourceFormat format = RGBA_8888;
1988 ResourceProvider::ResourceId resource =
1989 child_resource_provider_->CreateResource(
1990 size,
1991 GL_CLAMP_TO_EDGE,
1992 ResourceProvider::TextureHintImmutable,
1993 format);
1994 child_resource_provider_->AllocateForTesting(resource);
1995 // Expect a GL resource to be lost.
1996 bool should_lose_resource = GetParam() == ResourceProvider::GLTexture;
1998 ReturnedResourceArray returned_to_child;
1999 int child_id =
2000 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
2002 // Transfer the resource to the parent.
2003 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2004 resource_ids_to_transfer.push_back(resource);
2005 TransferableResourceArray list;
2006 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
2007 &list);
2008 EXPECT_EQ(1u, list.size());
2010 resource_provider_->ReceiveFromChild(child_id, list);
2011 resource_provider_->DeclareUsedResourcesFromChild(child_id,
2012 resource_ids_to_transfer);
2015 // Lose the output surface in the parent.
2016 resource_provider_->DidLoseOutputSurface();
2019 EXPECT_EQ(0u, returned_to_child.size());
2021 // Transfer resources back from the parent to the child. Set no resources as
2022 // being in use.
2023 ResourceProvider::ResourceIdArray no_resources;
2024 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
2026 // Expect a GL resource to be lost.
2027 ASSERT_EQ(1u, returned_to_child.size());
2028 EXPECT_EQ(should_lose_resource, returned_to_child[0].lost);
2029 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
2030 returned_to_child.clear();
2033 // A GL resource should be lost.
2034 EXPECT_EQ(should_lose_resource, child_resource_provider_->IsLost(resource));
2036 // Lost resources stay in use in the parent forever.
2037 EXPECT_EQ(should_lose_resource,
2038 child_resource_provider_->InUseByConsumer(resource));
2041 TEST_P(ResourceProviderTest, LostResourceInGrandParent) {
2042 gfx::Size size(1, 1);
2043 ResourceFormat format = RGBA_8888;
2044 ResourceProvider::ResourceId resource =
2045 child_resource_provider_->CreateResource(
2046 size,
2047 GL_CLAMP_TO_EDGE,
2048 ResourceProvider::TextureHintImmutable,
2049 format);
2050 child_resource_provider_->AllocateForTesting(resource);
2052 ReturnedResourceArray returned_to_child;
2053 int child_id =
2054 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
2056 // Transfer the resource to the parent.
2057 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2058 resource_ids_to_transfer.push_back(resource);
2059 TransferableResourceArray list;
2060 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
2061 &list);
2062 EXPECT_EQ(1u, list.size());
2064 resource_provider_->ReceiveFromChild(child_id, list);
2065 resource_provider_->DeclareUsedResourcesFromChild(child_id,
2066 resource_ids_to_transfer);
2070 ResourceProvider::ResourceIdMap resource_map =
2071 resource_provider_->GetChildToParentMap(child_id);
2072 ResourceProvider::ResourceId parent_resource = resource_map[resource];
2073 EXPECT_NE(0u, parent_resource);
2075 // Transfer to a grandparent.
2076 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2077 resource_ids_to_transfer.push_back(parent_resource);
2078 TransferableResourceArray list;
2079 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
2081 // Receive back a lost resource from the grandparent.
2082 EXPECT_EQ(1u, list.size());
2083 EXPECT_EQ(parent_resource, list[0].id);
2084 ReturnedResourceArray returned;
2085 TransferableResource::ReturnResources(list, &returned);
2086 EXPECT_EQ(1u, returned.size());
2087 EXPECT_EQ(parent_resource, returned[0].id);
2088 returned[0].lost = true;
2089 resource_provider_->ReceiveReturnsFromParent(returned);
2091 // The resource should be lost.
2092 EXPECT_TRUE(resource_provider_->IsLost(parent_resource));
2094 // Lost resources stay in use in the parent forever.
2095 EXPECT_TRUE(resource_provider_->InUseByConsumer(parent_resource));
2099 EXPECT_EQ(0u, returned_to_child.size());
2101 // Transfer resources back from the parent to the child. Set no resources as
2102 // being in use.
2103 ResourceProvider::ResourceIdArray no_resources;
2104 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
2106 // Expect the resource to be lost.
2107 ASSERT_EQ(1u, returned_to_child.size());
2108 EXPECT_TRUE(returned_to_child[0].lost);
2109 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
2110 returned_to_child.clear();
2113 // The resource should be lost.
2114 EXPECT_TRUE(child_resource_provider_->IsLost(resource));
2116 // Lost resources stay in use in the parent forever.
2117 EXPECT_TRUE(child_resource_provider_->InUseByConsumer(resource));
2120 TEST_P(ResourceProviderTest, LostMailboxInParent) {
2121 uint32 release_sync_point = 0;
2122 bool lost_resource = false;
2123 bool release_called = false;
2124 uint32 sync_point = 0;
2125 ResourceProvider::ResourceId resource = CreateChildMailbox(
2126 &release_sync_point, &lost_resource, &release_called, &sync_point);
2128 ReturnedResourceArray returned_to_child;
2129 int child_id =
2130 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
2132 // Transfer the resource to the parent.
2133 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2134 resource_ids_to_transfer.push_back(resource);
2135 TransferableResourceArray list;
2136 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
2137 &list);
2138 EXPECT_EQ(1u, list.size());
2140 resource_provider_->ReceiveFromChild(child_id, list);
2141 resource_provider_->DeclareUsedResourcesFromChild(child_id,
2142 resource_ids_to_transfer);
2145 // Lose the output surface in the parent.
2146 resource_provider_->DidLoseOutputSurface();
2149 EXPECT_EQ(0u, returned_to_child.size());
2151 // Transfer resources back from the parent to the child. Set no resources as
2152 // being in use.
2153 ResourceProvider::ResourceIdArray no_resources;
2154 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
2156 ASSERT_EQ(1u, returned_to_child.size());
2157 // Losing an output surface only loses hardware resources.
2158 EXPECT_EQ(returned_to_child[0].lost,
2159 GetParam() == ResourceProvider::GLTexture);
2160 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
2161 returned_to_child.clear();
2164 // Delete the resource in the child. Expect the resource to be lost if it's
2165 // a GL texture.
2166 child_resource_provider_->DeleteResource(resource);
2167 EXPECT_EQ(lost_resource, GetParam() == ResourceProvider::GLTexture);
2170 TEST_P(ResourceProviderTest, LostMailboxInGrandParent) {
2171 uint32 release_sync_point = 0;
2172 bool lost_resource = false;
2173 bool release_called = false;
2174 uint32 sync_point = 0;
2175 ResourceProvider::ResourceId resource = CreateChildMailbox(
2176 &release_sync_point, &lost_resource, &release_called, &sync_point);
2178 ReturnedResourceArray returned_to_child;
2179 int child_id =
2180 resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
2182 // Transfer the resource to the parent.
2183 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2184 resource_ids_to_transfer.push_back(resource);
2185 TransferableResourceArray list;
2186 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
2187 &list);
2188 EXPECT_EQ(1u, list.size());
2190 resource_provider_->ReceiveFromChild(child_id, list);
2191 resource_provider_->DeclareUsedResourcesFromChild(child_id,
2192 resource_ids_to_transfer);
2196 ResourceProvider::ResourceIdMap resource_map =
2197 resource_provider_->GetChildToParentMap(child_id);
2198 ResourceProvider::ResourceId parent_resource = resource_map[resource];
2199 EXPECT_NE(0u, parent_resource);
2201 // Transfer to a grandparent.
2202 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2203 resource_ids_to_transfer.push_back(parent_resource);
2204 TransferableResourceArray list;
2205 resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list);
2207 // Receive back a lost resource from the grandparent.
2208 EXPECT_EQ(1u, list.size());
2209 EXPECT_EQ(parent_resource, list[0].id);
2210 ReturnedResourceArray returned;
2211 TransferableResource::ReturnResources(list, &returned);
2212 EXPECT_EQ(1u, returned.size());
2213 EXPECT_EQ(parent_resource, returned[0].id);
2214 returned[0].lost = true;
2215 resource_provider_->ReceiveReturnsFromParent(returned);
2219 EXPECT_EQ(0u, returned_to_child.size());
2221 // Transfer resources back from the parent to the child. Set no resources as
2222 // being in use.
2223 ResourceProvider::ResourceIdArray no_resources;
2224 resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
2226 // Expect the resource to be lost.
2227 ASSERT_EQ(1u, returned_to_child.size());
2228 EXPECT_TRUE(returned_to_child[0].lost);
2229 child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
2230 returned_to_child.clear();
2233 // Delete the resource in the child. Expect the resource to be lost.
2234 child_resource_provider_->DeleteResource(resource);
2235 EXPECT_TRUE(lost_resource);
2238 TEST_P(ResourceProviderTest, Shutdown) {
2239 uint32 release_sync_point = 0;
2240 bool lost_resource = false;
2241 bool release_called = false;
2242 uint32 sync_point = 0;
2243 CreateChildMailbox(
2244 &release_sync_point, &lost_resource, &release_called, &sync_point);
2246 EXPECT_EQ(0u, release_sync_point);
2247 EXPECT_FALSE(lost_resource);
2249 child_resource_provider_.reset();
2251 if (GetParam() == ResourceProvider::GLTexture) {
2252 EXPECT_LE(sync_point, release_sync_point);
2254 EXPECT_TRUE(release_called);
2255 EXPECT_FALSE(lost_resource);
2258 TEST_P(ResourceProviderTest, ShutdownWithExportedResource) {
2259 uint32 release_sync_point = 0;
2260 bool lost_resource = false;
2261 bool release_called = false;
2262 uint32 sync_point = 0;
2263 ResourceProvider::ResourceId resource = CreateChildMailbox(
2264 &release_sync_point, &lost_resource, &release_called, &sync_point);
2266 // Transfer the resource, so we can't release it properly on shutdown.
2267 ResourceProvider::ResourceIdArray resource_ids_to_transfer;
2268 resource_ids_to_transfer.push_back(resource);
2269 TransferableResourceArray list;
2270 child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
2271 &list);
2273 EXPECT_EQ(0u, release_sync_point);
2274 EXPECT_FALSE(lost_resource);
2276 child_resource_provider_.reset();
2278 // Since the resource is in the parent, the child considers it lost.
2279 EXPECT_EQ(0u, release_sync_point);
2280 EXPECT_TRUE(lost_resource);
2283 TEST_P(ResourceProviderTest, LostContext) {
2284 // TextureMailbox callbacks only exist for GL textures for now.
2285 if (GetParam() != ResourceProvider::GLTexture)
2286 return;
2287 unsigned texture = context()->createTexture();
2288 context()->bindTexture(GL_TEXTURE_2D, texture);
2289 gpu::Mailbox mailbox;
2290 context()->genMailboxCHROMIUM(mailbox.name);
2291 context()->produceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
2292 uint32 sync_point = context()->insertSyncPoint();
2294 EXPECT_LT(0u, sync_point);
2296 uint32 release_sync_point = 0;
2297 bool lost_resource = false;
2298 BlockingTaskRunner* main_thread_task_runner = NULL;
2299 scoped_ptr<SingleReleaseCallbackImpl> callback =
2300 SingleReleaseCallbackImpl::Create(base::Bind(ReleaseCallback,
2301 &release_sync_point,
2302 &lost_resource,
2303 &main_thread_task_runner));
2304 resource_provider_->CreateResourceFromTextureMailbox(
2305 TextureMailbox(mailbox, GL_TEXTURE_2D, sync_point), callback.Pass());
2307 EXPECT_EQ(0u, release_sync_point);
2308 EXPECT_FALSE(lost_resource);
2309 EXPECT_EQ(NULL, main_thread_task_runner);
2311 resource_provider_->DidLoseOutputSurface();
2312 resource_provider_.reset();
2314 EXPECT_LE(sync_point, release_sync_point);
2315 EXPECT_TRUE(lost_resource);
2316 EXPECT_EQ(main_thread_task_runner_.get(), main_thread_task_runner);
2319 TEST_P(ResourceProviderTest, ScopedSampler) {
2320 // Sampling is only supported for GL textures.
2321 if (GetParam() != ResourceProvider::GLTexture)
2322 return;
2324 scoped_ptr<TextureStateTrackingContext> context_owned(
2325 new TextureStateTrackingContext);
2326 TextureStateTrackingContext* context = context_owned.get();
2328 FakeOutputSurfaceClient output_surface_client;
2329 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
2330 context_owned.PassAs<TestWebGraphicsContext3D>()));
2331 CHECK(output_surface->BindToClient(&output_surface_client));
2333 scoped_ptr<ResourceProvider> resource_provider(
2334 ResourceProvider::Create(output_surface.get(),
2335 shared_bitmap_manager_.get(),
2336 NULL,
2338 false,
2340 false));
2342 gfx::Size size(1, 1);
2343 ResourceFormat format = RGBA_8888;
2344 int texture_id = 1;
2346 ResourceProvider::ResourceId id = resource_provider->CreateResource(
2347 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
2349 // Check that the texture gets created with the right sampler settings.
2350 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id))
2351 .Times(2); // Once to create and once to allocate.
2352 EXPECT_CALL(*context,
2353 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
2354 EXPECT_CALL(*context,
2355 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
2356 EXPECT_CALL(
2357 *context,
2358 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
2359 EXPECT_CALL(
2360 *context,
2361 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
2362 EXPECT_CALL(*context,
2363 texParameteri(GL_TEXTURE_2D,
2364 GL_TEXTURE_POOL_CHROMIUM,
2365 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM));
2367 resource_provider->AllocateForTesting(id);
2368 Mock::VerifyAndClearExpectations(context);
2370 // Creating a sampler with the default filter should not change any texture
2371 // parameters.
2373 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
2374 ResourceProvider::ScopedSamplerGL sampler(
2375 resource_provider.get(), id, GL_TEXTURE_2D, GL_LINEAR);
2376 Mock::VerifyAndClearExpectations(context);
2379 // Using a different filter should be reflected in the texture parameters.
2381 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
2382 EXPECT_CALL(
2383 *context,
2384 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
2385 EXPECT_CALL(
2386 *context,
2387 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
2388 ResourceProvider::ScopedSamplerGL sampler(
2389 resource_provider.get(), id, GL_TEXTURE_2D, GL_NEAREST);
2390 Mock::VerifyAndClearExpectations(context);
2393 // Test resetting to the default filter.
2395 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
2396 EXPECT_CALL(*context,
2397 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
2398 EXPECT_CALL(*context,
2399 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
2400 ResourceProvider::ScopedSamplerGL sampler(
2401 resource_provider.get(), id, GL_TEXTURE_2D, GL_LINEAR);
2402 Mock::VerifyAndClearExpectations(context);
2406 TEST_P(ResourceProviderTest, ManagedResource) {
2407 // Sampling is only supported for GL textures.
2408 if (GetParam() != ResourceProvider::GLTexture)
2409 return;
2411 scoped_ptr<TextureStateTrackingContext> context_owned(
2412 new TextureStateTrackingContext);
2413 TextureStateTrackingContext* context = context_owned.get();
2415 FakeOutputSurfaceClient output_surface_client;
2416 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
2417 context_owned.PassAs<TestWebGraphicsContext3D>()));
2418 CHECK(output_surface->BindToClient(&output_surface_client));
2420 scoped_ptr<ResourceProvider> resource_provider(
2421 ResourceProvider::Create(output_surface.get(),
2422 shared_bitmap_manager_.get(),
2423 NULL,
2425 false,
2427 false));
2429 gfx::Size size(1, 1);
2430 ResourceFormat format = RGBA_8888;
2431 int texture_id = 1;
2433 // Check that the texture gets created with the right sampler settings.
2434 ResourceProvider::ResourceId id = resource_provider->CreateManagedResource(
2435 size,
2436 GL_TEXTURE_2D,
2437 GL_CLAMP_TO_EDGE,
2438 ResourceProvider::TextureHintImmutable,
2439 format);
2440 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
2441 EXPECT_CALL(*context,
2442 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
2443 EXPECT_CALL(*context,
2444 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
2445 EXPECT_CALL(
2446 *context,
2447 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
2448 EXPECT_CALL(
2449 *context,
2450 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
2451 EXPECT_CALL(*context,
2452 texParameteri(GL_TEXTURE_2D,
2453 GL_TEXTURE_POOL_CHROMIUM,
2454 GL_TEXTURE_POOL_MANAGED_CHROMIUM));
2455 resource_provider->CreateForTesting(id);
2456 EXPECT_NE(0u, id);
2458 Mock::VerifyAndClearExpectations(context);
2461 TEST_P(ResourceProviderTest, TextureWrapMode) {
2462 // Sampling is only supported for GL textures.
2463 if (GetParam() != ResourceProvider::GLTexture)
2464 return;
2466 scoped_ptr<TextureStateTrackingContext> context_owned(
2467 new TextureStateTrackingContext);
2468 TextureStateTrackingContext* context = context_owned.get();
2470 FakeOutputSurfaceClient output_surface_client;
2471 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
2472 context_owned.PassAs<TestWebGraphicsContext3D>()));
2473 CHECK(output_surface->BindToClient(&output_surface_client));
2475 scoped_ptr<ResourceProvider> resource_provider(
2476 ResourceProvider::Create(output_surface.get(),
2477 shared_bitmap_manager_.get(),
2478 NULL,
2480 false,
2482 false));
2484 gfx::Size size(1, 1);
2485 ResourceFormat format = RGBA_8888;
2486 GLenum texture_pool = GL_TEXTURE_POOL_UNMANAGED_CHROMIUM;
2488 for (int texture_id = 1; texture_id <= 2; ++texture_id) {
2489 GLint wrap_mode = texture_id == 1 ? GL_CLAMP_TO_EDGE : GL_REPEAT;
2490 // Check that the texture gets created with the right sampler settings.
2491 ResourceProvider::ResourceId id = resource_provider->CreateGLTexture(
2492 size,
2493 GL_TEXTURE_2D,
2494 texture_pool,
2495 wrap_mode,
2496 ResourceProvider::TextureHintImmutable,
2497 format);
2498 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
2499 EXPECT_CALL(*context,
2500 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
2501 EXPECT_CALL(*context,
2502 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
2503 EXPECT_CALL(*context,
2504 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap_mode));
2505 EXPECT_CALL(*context,
2506 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap_mode));
2507 EXPECT_CALL(*context,
2508 texParameteri(GL_TEXTURE_2D,
2509 GL_TEXTURE_POOL_CHROMIUM,
2510 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM));
2511 resource_provider->CreateForTesting(id);
2512 EXPECT_NE(0u, id);
2514 Mock::VerifyAndClearExpectations(context);
2518 TEST_P(ResourceProviderTest, TextureHint) {
2519 // Sampling is only supported for GL textures.
2520 if (GetParam() != ResourceProvider::GLTexture)
2521 return;
2523 scoped_ptr<TextureStateTrackingContext> context_owned(
2524 new TextureStateTrackingContext);
2525 TextureStateTrackingContext* context = context_owned.get();
2526 context->set_support_texture_storage(true);
2527 context->set_support_texture_usage(true);
2529 FakeOutputSurfaceClient output_surface_client;
2530 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
2531 context_owned.PassAs<TestWebGraphicsContext3D>()));
2532 CHECK(output_surface->BindToClient(&output_surface_client));
2534 scoped_ptr<ResourceProvider> resource_provider(
2535 ResourceProvider::Create(output_surface.get(),
2536 shared_bitmap_manager_.get(),
2537 NULL,
2539 false,
2541 false));
2543 gfx::Size size(1, 1);
2544 ResourceFormat format = RGBA_8888;
2545 GLenum texture_pool = GL_TEXTURE_POOL_UNMANAGED_CHROMIUM;
2547 const ResourceProvider::TextureHint hints[4] = {
2548 ResourceProvider::TextureHintDefault,
2549 ResourceProvider::TextureHintImmutable,
2550 ResourceProvider::TextureHintFramebuffer,
2551 ResourceProvider::TextureHintImmutableFramebuffer,
2553 for (GLuint texture_id = 1; texture_id <= arraysize(hints); ++texture_id) {
2554 // Check that the texture gets created with the right sampler settings.
2555 ResourceProvider::ResourceId id =
2556 resource_provider->CreateGLTexture(size,
2557 GL_TEXTURE_2D,
2558 texture_pool,
2559 GL_CLAMP_TO_EDGE,
2560 hints[texture_id - 1],
2561 format);
2562 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
2563 EXPECT_CALL(*context,
2564 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
2565 EXPECT_CALL(*context,
2566 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
2567 EXPECT_CALL(
2568 *context,
2569 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
2570 EXPECT_CALL(
2571 *context,
2572 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
2573 EXPECT_CALL(*context,
2574 texParameteri(GL_TEXTURE_2D,
2575 GL_TEXTURE_POOL_CHROMIUM,
2576 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM));
2577 // Check only TextureHintFramebuffer set GL_TEXTURE_USAGE_ANGLE.
2578 bool is_framebuffer_hint =
2579 hints[texture_id - 1] & ResourceProvider::TextureHintFramebuffer;
2580 EXPECT_CALL(*context,
2581 texParameteri(GL_TEXTURE_2D,
2582 GL_TEXTURE_USAGE_ANGLE,
2583 GL_FRAMEBUFFER_ATTACHMENT_ANGLE))
2584 .Times(is_framebuffer_hint ? 1 : 0);
2585 resource_provider->CreateForTesting(id);
2586 EXPECT_NE(0u, id);
2588 Mock::VerifyAndClearExpectations(context);
2592 TEST_P(ResourceProviderTest, TextureMailbox_SharedMemory) {
2593 if (GetParam() != ResourceProvider::Bitmap)
2594 return;
2596 gfx::Size size(64, 64);
2597 const uint32_t kBadBeef = 0xbadbeef;
2598 scoped_ptr<base::SharedMemory> shared_memory(
2599 CreateAndFillSharedMemory(size, kBadBeef));
2601 FakeOutputSurfaceClient output_surface_client;
2602 scoped_ptr<OutputSurface> output_surface(
2603 FakeOutputSurface::CreateSoftware(make_scoped_ptr(
2604 new SoftwareOutputDevice)));
2605 CHECK(output_surface->BindToClient(&output_surface_client));
2607 scoped_ptr<ResourceProvider> resource_provider(
2608 ResourceProvider::Create(output_surface.get(),
2609 shared_bitmap_manager_.get(),
2610 main_thread_task_runner_.get(),
2612 false,
2614 false));
2616 uint32 release_sync_point = 0;
2617 bool lost_resource = false;
2618 BlockingTaskRunner* main_thread_task_runner = NULL;
2619 scoped_ptr<SingleReleaseCallbackImpl> callback =
2620 SingleReleaseCallbackImpl::Create(base::Bind(&ReleaseCallback,
2621 &release_sync_point,
2622 &lost_resource,
2623 &main_thread_task_runner));
2624 TextureMailbox mailbox(shared_memory.get(), size);
2626 ResourceProvider::ResourceId id =
2627 resource_provider->CreateResourceFromTextureMailbox(
2628 mailbox, callback.Pass());
2629 EXPECT_NE(0u, id);
2632 ResourceProvider::ScopedReadLockSoftware lock(resource_provider.get(), id);
2633 const SkBitmap* sk_bitmap = lock.sk_bitmap();
2634 EXPECT_EQ(sk_bitmap->width(), size.width());
2635 EXPECT_EQ(sk_bitmap->height(), size.height());
2636 EXPECT_EQ(*sk_bitmap->getAddr32(16, 16), kBadBeef);
2639 resource_provider->DeleteResource(id);
2640 EXPECT_EQ(0u, release_sync_point);
2641 EXPECT_FALSE(lost_resource);
2642 EXPECT_EQ(main_thread_task_runner_.get(), main_thread_task_runner);
2645 TEST_P(ResourceProviderTest, TextureMailbox_GLTexture2D) {
2646 // Mailboxing is only supported for GL textures.
2647 if (GetParam() != ResourceProvider::GLTexture)
2648 return;
2650 scoped_ptr<TextureStateTrackingContext> context_owned(
2651 new TextureStateTrackingContext);
2652 TextureStateTrackingContext* context = context_owned.get();
2654 FakeOutputSurfaceClient output_surface_client;
2655 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
2656 context_owned.PassAs<TestWebGraphicsContext3D>()));
2657 CHECK(output_surface->BindToClient(&output_surface_client));
2659 scoped_ptr<ResourceProvider> resource_provider(
2660 ResourceProvider::Create(output_surface.get(),
2661 shared_bitmap_manager_.get(),
2662 main_thread_task_runner_.get(),
2664 false,
2666 false));
2668 unsigned texture_id = 1;
2669 uint32 sync_point = 30;
2670 unsigned target = GL_TEXTURE_2D;
2672 EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
2673 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
2674 EXPECT_CALL(*context, insertSyncPoint()).Times(0);
2675 EXPECT_CALL(*context, produceTextureCHROMIUM(_, _)).Times(0);
2676 EXPECT_CALL(*context, consumeTextureCHROMIUM(_, _)).Times(0);
2678 gpu::Mailbox gpu_mailbox;
2679 memcpy(gpu_mailbox.name, "Hello world", strlen("Hello world") + 1);
2680 uint32 release_sync_point = 0;
2681 bool lost_resource = false;
2682 BlockingTaskRunner* main_thread_task_runner = NULL;
2683 scoped_ptr<SingleReleaseCallbackImpl> callback =
2684 SingleReleaseCallbackImpl::Create(base::Bind(&ReleaseCallback,
2685 &release_sync_point,
2686 &lost_resource,
2687 &main_thread_task_runner));
2689 TextureMailbox mailbox(gpu_mailbox, target, sync_point);
2691 ResourceProvider::ResourceId id =
2692 resource_provider->CreateResourceFromTextureMailbox(
2693 mailbox, callback.Pass());
2694 EXPECT_NE(0u, id);
2696 Mock::VerifyAndClearExpectations(context);
2699 // Mailbox sync point WaitSyncPoint before using the texture.
2700 EXPECT_CALL(*context, waitSyncPoint(sync_point));
2701 resource_provider->WaitSyncPointIfNeeded(id);
2702 Mock::VerifyAndClearExpectations(context);
2704 // Using the texture does a consume of the mailbox.
2705 EXPECT_CALL(*context, bindTexture(target, texture_id));
2706 EXPECT_CALL(*context, consumeTextureCHROMIUM(target, _));
2708 EXPECT_CALL(*context, insertSyncPoint()).Times(0);
2709 EXPECT_CALL(*context, produceTextureCHROMIUM(_, _)).Times(0);
2711 ResourceProvider::ScopedReadLockGL lock(resource_provider.get(), id);
2712 Mock::VerifyAndClearExpectations(context);
2714 // When done with it, a sync point should be inserted, but no produce is
2715 // necessary.
2716 EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
2717 EXPECT_CALL(*context, insertSyncPoint());
2718 EXPECT_CALL(*context, produceTextureCHROMIUM(_, _)).Times(0);
2720 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
2721 EXPECT_CALL(*context, consumeTextureCHROMIUM(_, _)).Times(0);
2724 resource_provider->DeleteResource(id);
2725 EXPECT_EQ(0u, release_sync_point);
2726 EXPECT_FALSE(lost_resource);
2727 EXPECT_EQ(main_thread_task_runner_.get(), main_thread_task_runner);
2730 TEST_P(ResourceProviderTest, TextureMailbox_GLTextureExternalOES) {
2731 // Mailboxing is only supported for GL textures.
2732 if (GetParam() != ResourceProvider::GLTexture)
2733 return;
2735 scoped_ptr<TextureStateTrackingContext> context_owned(
2736 new TextureStateTrackingContext);
2737 TextureStateTrackingContext* context = context_owned.get();
2739 FakeOutputSurfaceClient output_surface_client;
2740 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
2741 context_owned.PassAs<TestWebGraphicsContext3D>()));
2742 CHECK(output_surface->BindToClient(&output_surface_client));
2744 scoped_ptr<ResourceProvider> resource_provider(
2745 ResourceProvider::Create(output_surface.get(),
2746 shared_bitmap_manager_.get(),
2747 NULL,
2749 false,
2751 false));
2753 unsigned texture_id = 1;
2754 uint32 sync_point = 30;
2755 unsigned target = GL_TEXTURE_EXTERNAL_OES;
2757 EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
2758 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
2759 EXPECT_CALL(*context, insertSyncPoint()).Times(0);
2760 EXPECT_CALL(*context, produceTextureCHROMIUM(_, _)).Times(0);
2761 EXPECT_CALL(*context, consumeTextureCHROMIUM(_, _)).Times(0);
2763 gpu::Mailbox gpu_mailbox;
2764 memcpy(gpu_mailbox.name, "Hello world", strlen("Hello world") + 1);
2765 scoped_ptr<SingleReleaseCallbackImpl> callback =
2766 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback));
2768 TextureMailbox mailbox(gpu_mailbox, target, sync_point);
2770 ResourceProvider::ResourceId id =
2771 resource_provider->CreateResourceFromTextureMailbox(
2772 mailbox, callback.Pass());
2773 EXPECT_NE(0u, id);
2775 Mock::VerifyAndClearExpectations(context);
2778 // Mailbox sync point WaitSyncPoint before using the texture.
2779 EXPECT_CALL(*context, waitSyncPoint(sync_point));
2780 resource_provider->WaitSyncPointIfNeeded(id);
2781 Mock::VerifyAndClearExpectations(context);
2783 // Using the texture does a consume of the mailbox.
2784 EXPECT_CALL(*context, bindTexture(target, texture_id));
2785 EXPECT_CALL(*context, consumeTextureCHROMIUM(target, _));
2787 EXPECT_CALL(*context, insertSyncPoint()).Times(0);
2788 EXPECT_CALL(*context, produceTextureCHROMIUM(_, _)).Times(0);
2790 ResourceProvider::ScopedReadLockGL lock(resource_provider.get(), id);
2791 Mock::VerifyAndClearExpectations(context);
2793 // When done with it, a sync point should be inserted, but no produce is
2794 // necessary.
2795 EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
2796 EXPECT_CALL(*context, insertSyncPoint());
2797 EXPECT_CALL(*context, produceTextureCHROMIUM(_, _)).Times(0);
2799 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
2800 EXPECT_CALL(*context, consumeTextureCHROMIUM(_, _)).Times(0);
2804 TEST_P(ResourceProviderTest,
2805 TextureMailbox_WaitSyncPointIfNeeded_WithSyncPoint) {
2806 // Mailboxing is only supported for GL textures.
2807 if (GetParam() != ResourceProvider::GLTexture)
2808 return;
2810 scoped_ptr<TextureStateTrackingContext> context_owned(
2811 new TextureStateTrackingContext);
2812 TextureStateTrackingContext* context = context_owned.get();
2814 FakeOutputSurfaceClient output_surface_client;
2815 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
2816 context_owned.PassAs<TestWebGraphicsContext3D>()));
2817 CHECK(output_surface->BindToClient(&output_surface_client));
2819 scoped_ptr<ResourceProvider> resource_provider(
2820 ResourceProvider::Create(output_surface.get(),
2821 shared_bitmap_manager_.get(),
2822 NULL,
2824 false,
2826 false));
2828 uint32 sync_point = 30;
2829 unsigned target = GL_TEXTURE_2D;
2831 EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
2832 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
2833 EXPECT_CALL(*context, insertSyncPoint()).Times(0);
2834 EXPECT_CALL(*context, produceTextureCHROMIUM(_, _)).Times(0);
2835 EXPECT_CALL(*context, consumeTextureCHROMIUM(_, _)).Times(0);
2837 gpu::Mailbox gpu_mailbox;
2838 memcpy(gpu_mailbox.name, "Hello world", strlen("Hello world") + 1);
2839 scoped_ptr<SingleReleaseCallbackImpl> callback =
2840 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback));
2842 TextureMailbox mailbox(gpu_mailbox, target, sync_point);
2844 ResourceProvider::ResourceId id =
2845 resource_provider->CreateResourceFromTextureMailbox(mailbox,
2846 callback.Pass());
2847 EXPECT_NE(0u, id);
2849 Mock::VerifyAndClearExpectations(context);
2852 // First call to WaitSyncPointIfNeeded should call waitSyncPoint.
2853 EXPECT_CALL(*context, waitSyncPoint(sync_point));
2854 resource_provider->WaitSyncPointIfNeeded(id);
2855 Mock::VerifyAndClearExpectations(context);
2857 // Subsequent calls to WaitSyncPointIfNeeded shouldn't call waitSyncPoint.
2858 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
2859 resource_provider->WaitSyncPointIfNeeded(id);
2860 Mock::VerifyAndClearExpectations(context);
2864 TEST_P(ResourceProviderTest, TextureMailbox_WaitSyncPointIfNeeded_NoSyncPoint) {
2865 // Mailboxing is only supported for GL textures.
2866 if (GetParam() != ResourceProvider::GLTexture)
2867 return;
2869 scoped_ptr<TextureStateTrackingContext> context_owned(
2870 new TextureStateTrackingContext);
2871 TextureStateTrackingContext* context = context_owned.get();
2873 FakeOutputSurfaceClient output_surface_client;
2874 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
2875 context_owned.PassAs<TestWebGraphicsContext3D>()));
2876 CHECK(output_surface->BindToClient(&output_surface_client));
2878 scoped_ptr<ResourceProvider> resource_provider(
2879 ResourceProvider::Create(output_surface.get(),
2880 shared_bitmap_manager_.get(),
2881 NULL,
2883 false,
2885 false));
2887 uint32 sync_point = 0;
2888 unsigned target = GL_TEXTURE_2D;
2890 EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
2891 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
2892 EXPECT_CALL(*context, insertSyncPoint()).Times(0);
2893 EXPECT_CALL(*context, produceTextureCHROMIUM(_, _)).Times(0);
2894 EXPECT_CALL(*context, consumeTextureCHROMIUM(_, _)).Times(0);
2896 gpu::Mailbox gpu_mailbox;
2897 memcpy(gpu_mailbox.name, "Hello world", strlen("Hello world") + 1);
2898 scoped_ptr<SingleReleaseCallbackImpl> callback =
2899 SingleReleaseCallbackImpl::Create(base::Bind(&EmptyReleaseCallback));
2901 TextureMailbox mailbox(gpu_mailbox, target, sync_point);
2903 ResourceProvider::ResourceId id =
2904 resource_provider->CreateResourceFromTextureMailbox(mailbox,
2905 callback.Pass());
2906 EXPECT_NE(0u, id);
2908 Mock::VerifyAndClearExpectations(context);
2911 // WaitSyncPointIfNeeded with sync_point == 0 shouldn't call waitSyncPoint.
2912 EXPECT_CALL(*context, waitSyncPoint(_)).Times(0);
2913 resource_provider->WaitSyncPointIfNeeded(id);
2914 Mock::VerifyAndClearExpectations(context);
2918 class AllocationTrackingContext3D : public TestWebGraphicsContext3D {
2919 public:
2920 MOCK_METHOD0(NextTextureId, GLuint());
2921 MOCK_METHOD1(RetireTextureId, void(GLuint id));
2922 MOCK_METHOD2(bindTexture, void(GLenum target, GLuint texture));
2923 MOCK_METHOD5(texStorage2DEXT,
2924 void(GLenum target,
2925 GLint levels,
2926 GLuint internalformat,
2927 GLint width,
2928 GLint height));
2929 MOCK_METHOD9(texImage2D,
2930 void(GLenum target,
2931 GLint level,
2932 GLenum internalformat,
2933 GLsizei width,
2934 GLsizei height,
2935 GLint border,
2936 GLenum format,
2937 GLenum type,
2938 const void* pixels));
2939 MOCK_METHOD9(texSubImage2D,
2940 void(GLenum target,
2941 GLint level,
2942 GLint xoffset,
2943 GLint yoffset,
2944 GLsizei width,
2945 GLsizei height,
2946 GLenum format,
2947 GLenum type,
2948 const void* pixels));
2949 MOCK_METHOD9(asyncTexImage2DCHROMIUM,
2950 void(GLenum target,
2951 GLint level,
2952 GLenum internalformat,
2953 GLsizei width,
2954 GLsizei height,
2955 GLint border,
2956 GLenum format,
2957 GLenum type,
2958 const void* pixels));
2959 MOCK_METHOD9(asyncTexSubImage2DCHROMIUM,
2960 void(GLenum target,
2961 GLint level,
2962 GLint xoffset,
2963 GLint yoffset,
2964 GLsizei width,
2965 GLsizei height,
2966 GLenum format,
2967 GLenum type,
2968 const void* pixels));
2969 MOCK_METHOD8(compressedTexImage2D,
2970 void(GLenum target,
2971 GLint level,
2972 GLenum internalformat,
2973 GLsizei width,
2974 GLsizei height,
2975 GLint border,
2976 GLsizei image_size,
2977 const void* data));
2978 MOCK_METHOD1(waitAsyncTexImage2DCHROMIUM, void(GLenum));
2979 MOCK_METHOD4(createImageCHROMIUM, GLuint(GLsizei, GLsizei, GLenum, GLenum));
2980 MOCK_METHOD1(destroyImageCHROMIUM, void(GLuint));
2981 MOCK_METHOD1(mapImageCHROMIUM, void*(GLuint));
2982 MOCK_METHOD3(getImageParameterivCHROMIUM, void(GLuint, GLenum, GLint*));
2983 MOCK_METHOD1(unmapImageCHROMIUM, void(GLuint));
2984 MOCK_METHOD2(bindTexImage2DCHROMIUM, void(GLenum, GLint));
2985 MOCK_METHOD2(releaseTexImage2DCHROMIUM, void(GLenum, GLint));
2987 // We're mocking bindTexture, so we override
2988 // TestWebGraphicsContext3D::texParameteri to avoid assertions related to the
2989 // currently bound texture.
2990 virtual void texParameteri(GLenum target, GLenum pname, GLint param) {}
2993 TEST_P(ResourceProviderTest, TextureAllocation) {
2994 // Only for GL textures.
2995 if (GetParam() != ResourceProvider::GLTexture)
2996 return;
2997 scoped_ptr<AllocationTrackingContext3D> context_owned(
2998 new StrictMock<AllocationTrackingContext3D>);
2999 AllocationTrackingContext3D* context = context_owned.get();
3001 FakeOutputSurfaceClient output_surface_client;
3002 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
3003 context_owned.PassAs<TestWebGraphicsContext3D>()));
3004 CHECK(output_surface->BindToClient(&output_surface_client));
3006 scoped_ptr<ResourceProvider> resource_provider(
3007 ResourceProvider::Create(output_surface.get(),
3008 shared_bitmap_manager_.get(),
3009 NULL,
3011 false,
3013 false));
3015 gfx::Size size(2, 2);
3016 gfx::Vector2d offset(0, 0);
3017 gfx::Rect rect(0, 0, 2, 2);
3018 ResourceFormat format = RGBA_8888;
3019 ResourceProvider::ResourceId id = 0;
3020 uint8_t pixels[16] = { 0 };
3021 int texture_id = 123;
3023 // Lazy allocation. Don't allocate when creating the resource.
3024 id = resource_provider->CreateResource(
3025 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
3027 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3028 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(1);
3029 resource_provider->CreateForTesting(id);
3031 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3032 resource_provider->DeleteResource(id);
3034 Mock::VerifyAndClearExpectations(context);
3036 // Do allocate when we set the pixels.
3037 id = resource_provider->CreateResource(
3038 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
3040 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3041 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(3);
3042 EXPECT_CALL(*context, texImage2D(_, _, _, 2, 2, _, _, _, _)).Times(1);
3043 EXPECT_CALL(*context, texSubImage2D(_, _, _, _, 2, 2, _, _, _)).Times(1);
3044 resource_provider->SetPixels(id, pixels, rect, rect, offset);
3046 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3047 resource_provider->DeleteResource(id);
3049 Mock::VerifyAndClearExpectations(context);
3051 // Same for async version.
3052 id = resource_provider->CreateResource(
3053 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
3054 RasterBuffer* raster_buffer = resource_provider->AcquirePixelRasterBuffer(id);
3055 skia::RefPtr<SkCanvas> canvas = raster_buffer->AcquireSkCanvas();
3056 raster_buffer->ReleaseSkCanvas(canvas);
3057 canvas.clear();
3059 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3060 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
3061 EXPECT_CALL(*context, asyncTexImage2DCHROMIUM(_, _, _, 2, 2, _, _, _, _))
3062 .Times(1);
3063 resource_provider->BeginSetPixels(id);
3064 ASSERT_TRUE(resource_provider->DidSetPixelsComplete(id));
3066 resource_provider->ReleasePixelRasterBuffer(id);
3068 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3069 resource_provider->DeleteResource(id);
3071 Mock::VerifyAndClearExpectations(context);
3074 TEST_P(ResourceProviderTest, TextureAllocationHint) {
3075 // Only for GL textures.
3076 if (GetParam() != ResourceProvider::GLTexture)
3077 return;
3078 scoped_ptr<AllocationTrackingContext3D> context_owned(
3079 new StrictMock<AllocationTrackingContext3D>);
3080 AllocationTrackingContext3D* context = context_owned.get();
3081 context->set_support_texture_storage(true);
3082 context->set_support_texture_usage(true);
3084 FakeOutputSurfaceClient output_surface_client;
3085 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
3086 context_owned.PassAs<TestWebGraphicsContext3D>()));
3087 CHECK(output_surface->BindToClient(&output_surface_client));
3089 scoped_ptr<ResourceProvider> resource_provider(
3090 ResourceProvider::Create(output_surface.get(),
3091 shared_bitmap_manager_.get(),
3092 NULL,
3094 false,
3096 false));
3098 gfx::Size size(2, 2);
3100 const ResourceFormat formats[2] = {RGBA_8888, BGRA_8888};
3101 const ResourceProvider::TextureHint hints[4] = {
3102 ResourceProvider::TextureHintDefault,
3103 ResourceProvider::TextureHintImmutable,
3104 ResourceProvider::TextureHintFramebuffer,
3105 ResourceProvider::TextureHintImmutableFramebuffer,
3107 for (size_t i = 0; i < arraysize(formats); ++i) {
3108 for (GLuint texture_id = 1; texture_id <= arraysize(hints); ++texture_id) {
3109 // Lazy allocation. Don't allocate when creating the resource.
3110 ResourceProvider::ResourceId id = resource_provider->CreateResource(
3111 size, GL_CLAMP_TO_EDGE, hints[texture_id - 1], formats[i]);
3113 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3114 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
3115 bool is_immutable_hint =
3116 hints[texture_id - 1] & ResourceProvider::TextureHintImmutable;
3117 bool support_immutable_texture =
3118 is_immutable_hint && formats[i] == RGBA_8888;
3119 EXPECT_CALL(*context, texStorage2DEXT(_, _, _, 2, 2))
3120 .Times(support_immutable_texture ? 1 : 0);
3121 EXPECT_CALL(*context, texImage2D(_, _, _, 2, 2, _, _, _, _))
3122 .Times(support_immutable_texture ? 0 : 1);
3123 resource_provider->AllocateForTesting(id);
3125 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3126 resource_provider->DeleteResource(id);
3128 Mock::VerifyAndClearExpectations(context);
3133 TEST_P(ResourceProviderTest, TextureAllocationHint_BGRA) {
3134 // Only for GL textures.
3135 if (GetParam() != ResourceProvider::GLTexture)
3136 return;
3137 scoped_ptr<AllocationTrackingContext3D> context_owned(
3138 new StrictMock<AllocationTrackingContext3D>);
3139 AllocationTrackingContext3D* context = context_owned.get();
3140 context->set_support_texture_format_bgra8888(true);
3141 context->set_support_texture_storage(true);
3142 context->set_support_texture_usage(true);
3144 FakeOutputSurfaceClient output_surface_client;
3145 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
3146 context_owned.PassAs<TestWebGraphicsContext3D>()));
3147 CHECK(output_surface->BindToClient(&output_surface_client));
3149 scoped_ptr<ResourceProvider> resource_provider(
3150 ResourceProvider::Create(output_surface.get(),
3151 shared_bitmap_manager_.get(),
3152 NULL,
3154 false,
3156 false));
3158 gfx::Size size(2, 2);
3159 const ResourceFormat formats[2] = {RGBA_8888, BGRA_8888};
3161 const ResourceProvider::TextureHint hints[4] = {
3162 ResourceProvider::TextureHintDefault,
3163 ResourceProvider::TextureHintImmutable,
3164 ResourceProvider::TextureHintFramebuffer,
3165 ResourceProvider::TextureHintImmutableFramebuffer,
3167 for (size_t i = 0; i < arraysize(formats); ++i) {
3168 for (GLuint texture_id = 1; texture_id <= arraysize(hints); ++texture_id) {
3169 // Lazy allocation. Don't allocate when creating the resource.
3170 ResourceProvider::ResourceId id = resource_provider->CreateResource(
3171 size, GL_CLAMP_TO_EDGE, hints[texture_id - 1], formats[i]);
3173 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3174 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
3175 bool is_immutable_hint =
3176 hints[texture_id - 1] & ResourceProvider::TextureHintImmutable;
3177 EXPECT_CALL(*context, texStorage2DEXT(_, _, _, 2, 2))
3178 .Times(is_immutable_hint ? 1 : 0);
3179 EXPECT_CALL(*context, texImage2D(_, _, _, 2, 2, _, _, _, _))
3180 .Times(is_immutable_hint ? 0 : 1);
3181 resource_provider->AllocateForTesting(id);
3183 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3184 resource_provider->DeleteResource(id);
3186 Mock::VerifyAndClearExpectations(context);
3191 TEST_P(ResourceProviderTest, PixelBuffer_GLTexture) {
3192 if (GetParam() != ResourceProvider::GLTexture)
3193 return;
3194 scoped_ptr<AllocationTrackingContext3D> context_owned(
3195 new StrictMock<AllocationTrackingContext3D>);
3196 AllocationTrackingContext3D* context = context_owned.get();
3198 FakeOutputSurfaceClient output_surface_client;
3199 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
3200 context_owned.PassAs<TestWebGraphicsContext3D>()));
3201 CHECK(output_surface->BindToClient(&output_surface_client));
3203 gfx::Size size(2, 2);
3204 ResourceFormat format = RGBA_8888;
3205 ResourceProvider::ResourceId id = 0;
3206 int texture_id = 123;
3208 scoped_ptr<ResourceProvider> resource_provider(
3209 ResourceProvider::Create(output_surface.get(),
3210 shared_bitmap_manager_.get(),
3211 NULL,
3213 false,
3215 false));
3217 id = resource_provider->CreateResource(
3218 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
3219 RasterBuffer* raster_buffer = resource_provider->AcquirePixelRasterBuffer(id);
3220 skia::RefPtr<SkCanvas> canvas = raster_buffer->AcquireSkCanvas();
3221 raster_buffer->ReleaseSkCanvas(canvas);
3222 canvas.clear();
3224 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3225 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
3226 EXPECT_CALL(*context, asyncTexImage2DCHROMIUM(_, _, _, 2, 2, _, _, _, _))
3227 .Times(1);
3228 resource_provider->BeginSetPixels(id);
3230 EXPECT_TRUE(resource_provider->DidSetPixelsComplete(id));
3232 resource_provider->ReleasePixelRasterBuffer(id);
3234 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3235 resource_provider->DeleteResource(id);
3237 Mock::VerifyAndClearExpectations(context);
3240 TEST_P(ResourceProviderTest, ForcingAsyncUploadToComplete) {
3241 // Only for GL textures.
3242 if (GetParam() != ResourceProvider::GLTexture)
3243 return;
3244 scoped_ptr<AllocationTrackingContext3D> context_owned(
3245 new StrictMock<AllocationTrackingContext3D>);
3246 AllocationTrackingContext3D* context = context_owned.get();
3248 FakeOutputSurfaceClient output_surface_client;
3249 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
3250 context_owned.PassAs<TestWebGraphicsContext3D>()));
3251 CHECK(output_surface->BindToClient(&output_surface_client));
3253 gfx::Size size(2, 2);
3254 ResourceFormat format = RGBA_8888;
3255 ResourceProvider::ResourceId id = 0;
3256 int texture_id = 123;
3258 scoped_ptr<ResourceProvider> resource_provider(
3259 ResourceProvider::Create(output_surface.get(),
3260 shared_bitmap_manager_.get(),
3261 NULL,
3263 false,
3265 false));
3267 id = resource_provider->CreateResource(
3268 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
3269 RasterBuffer* raster_buffer = resource_provider->AcquirePixelRasterBuffer(id);
3270 skia::RefPtr<SkCanvas> canvas = raster_buffer->AcquireSkCanvas();
3271 raster_buffer->ReleaseSkCanvas(canvas);
3272 canvas.clear();
3274 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3275 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
3276 EXPECT_CALL(*context, asyncTexImage2DCHROMIUM(_, _, _, 2, 2, _, _, _, _))
3277 .Times(1);
3278 resource_provider->BeginSetPixels(id);
3280 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(1);
3281 EXPECT_CALL(*context, waitAsyncTexImage2DCHROMIUM(GL_TEXTURE_2D)).Times(1);
3282 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, 0)).Times(1);
3283 resource_provider->ForceSetPixelsToComplete(id);
3285 resource_provider->ReleasePixelRasterBuffer(id);
3287 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3288 resource_provider->DeleteResource(id);
3290 Mock::VerifyAndClearExpectations(context);
3293 TEST_P(ResourceProviderTest, PixelBufferLostContext) {
3294 scoped_ptr<AllocationTrackingContext3D> context_owned(
3295 new NiceMock<AllocationTrackingContext3D>);
3296 AllocationTrackingContext3D* context = context_owned.get();
3298 FakeOutputSurfaceClient output_surface_client;
3299 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
3300 context_owned.PassAs<TestWebGraphicsContext3D>()));
3301 CHECK(output_surface->BindToClient(&output_surface_client));
3303 gfx::Size size(2, 2);
3304 ResourceFormat format = RGBA_8888;
3305 ResourceProvider::ResourceId id = 0;
3306 int texture_id = 123;
3308 scoped_ptr<ResourceProvider> resource_provider(
3309 ResourceProvider::Create(output_surface.get(),
3310 shared_bitmap_manager_.get(),
3311 NULL,
3313 false,
3315 false));
3317 EXPECT_CALL(*context, NextTextureId()).WillRepeatedly(Return(texture_id));
3319 id = resource_provider->CreateResource(
3320 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
3321 context->loseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB,
3322 GL_INNOCENT_CONTEXT_RESET_ARB);
3324 RasterBuffer* raster_buffer = resource_provider->AcquirePixelRasterBuffer(id);
3325 skia::RefPtr<SkCanvas> canvas = raster_buffer->AcquireSkCanvas();
3326 EXPECT_TRUE(canvas.get() == NULL);
3327 raster_buffer->ReleaseSkCanvas(canvas);
3328 canvas.clear();
3329 resource_provider->ReleasePixelRasterBuffer(id);
3330 Mock::VerifyAndClearExpectations(context);
3333 TEST_P(ResourceProviderTest, Image_GLTexture) {
3334 // Only for GL textures.
3335 if (GetParam() != ResourceProvider::GLTexture)
3336 return;
3337 scoped_ptr<AllocationTrackingContext3D> context_owned(
3338 new StrictMock<AllocationTrackingContext3D>);
3339 AllocationTrackingContext3D* context = context_owned.get();
3341 FakeOutputSurfaceClient output_surface_client;
3342 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
3343 context_owned.PassAs<TestWebGraphicsContext3D>()));
3344 CHECK(output_surface->BindToClient(&output_surface_client));
3346 const int kWidth = 2;
3347 const int kHeight = 2;
3348 gfx::Size size(kWidth, kHeight);
3349 ResourceFormat format = RGBA_8888;
3350 ResourceProvider::ResourceId id = 0;
3351 const unsigned kTextureId = 123u;
3352 const unsigned kImageId = 234u;
3354 scoped_ptr<ResourceProvider> resource_provider(
3355 ResourceProvider::Create(output_surface.get(),
3356 shared_bitmap_manager_.get(),
3357 NULL,
3359 false,
3361 false));
3363 id = resource_provider->CreateResource(
3364 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
3366 const int kStride = 4;
3367 void* dummy_mapped_buffer_address = NULL;
3368 EXPECT_CALL(
3369 *context,
3370 createImageCHROMIUM(kWidth, kHeight, GL_RGBA8_OES, GL_IMAGE_MAP_CHROMIUM))
3371 .WillOnce(Return(kImageId))
3372 .RetiresOnSaturation();
3373 EXPECT_CALL(*context, getImageParameterivCHROMIUM(kImageId,
3374 GL_IMAGE_ROWBYTES_CHROMIUM,
3376 .WillOnce(SetArgPointee<2>(kStride))
3377 .RetiresOnSaturation();
3378 EXPECT_CALL(*context, mapImageCHROMIUM(kImageId))
3379 .WillOnce(Return(dummy_mapped_buffer_address))
3380 .RetiresOnSaturation();
3381 resource_provider->AcquireImageRasterBuffer(id);
3382 resource_provider->ReleaseImageRasterBuffer(id);
3384 EXPECT_CALL(*context, NextTextureId())
3385 .WillOnce(Return(kTextureId))
3386 .RetiresOnSaturation();
3387 // Once in CreateTextureId and once in BindForSampling
3388 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kTextureId)).Times(2)
3389 .RetiresOnSaturation();
3390 EXPECT_CALL(*context, bindTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId))
3391 .Times(1)
3392 .RetiresOnSaturation();
3394 ResourceProvider::ScopedSamplerGL lock_gl(
3395 resource_provider.get(), id, GL_TEXTURE_2D, GL_LINEAR);
3396 EXPECT_EQ(kTextureId, lock_gl.texture_id());
3399 EXPECT_CALL(
3400 *context,
3401 getImageParameterivCHROMIUM(kImageId, GL_IMAGE_ROWBYTES_CHROMIUM, _))
3402 .WillOnce(SetArgPointee<2>(kStride))
3403 .RetiresOnSaturation();
3404 EXPECT_CALL(*context, mapImageCHROMIUM(kImageId))
3405 .WillOnce(Return(dummy_mapped_buffer_address))
3406 .RetiresOnSaturation();
3407 resource_provider->AcquireImageRasterBuffer(id);
3408 resource_provider->ReleaseImageRasterBuffer(id);
3410 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kTextureId)).Times(1)
3411 .RetiresOnSaturation();
3412 EXPECT_CALL(*context, releaseTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId))
3413 .Times(1)
3414 .RetiresOnSaturation();
3415 EXPECT_CALL(*context, bindTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId))
3416 .Times(1)
3417 .RetiresOnSaturation();
3418 EXPECT_CALL(*context, RetireTextureId(kTextureId))
3419 .Times(1)
3420 .RetiresOnSaturation();
3422 ResourceProvider::ScopedSamplerGL lock_gl(
3423 resource_provider.get(), id, GL_TEXTURE_2D, GL_LINEAR);
3424 EXPECT_EQ(kTextureId, lock_gl.texture_id());
3427 EXPECT_CALL(*context, destroyImageCHROMIUM(kImageId))
3428 .Times(1)
3429 .RetiresOnSaturation();
3432 TEST_P(ResourceProviderTest, Image_Bitmap) {
3433 if (GetParam() != ResourceProvider::Bitmap)
3434 return;
3435 FakeOutputSurfaceClient output_surface_client;
3436 scoped_ptr<OutputSurface> output_surface(
3437 FakeOutputSurface::CreateSoftware(make_scoped_ptr(
3438 new SoftwareOutputDevice)));
3439 CHECK(output_surface->BindToClient(&output_surface_client));
3441 gfx::Size size(1, 1);
3442 ResourceFormat format = RGBA_8888;
3443 ResourceProvider::ResourceId id = 0;
3444 const uint32_t kBadBeef = 0xbadbeef;
3446 scoped_ptr<ResourceProvider> resource_provider(
3447 ResourceProvider::Create(output_surface.get(),
3448 shared_bitmap_manager_.get(),
3449 NULL,
3451 false,
3453 false));
3455 id = resource_provider->CreateResource(
3456 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
3458 SkBitmap bitmap;
3459 bitmap.allocN32Pixels(size.width(), size.height());
3460 *(bitmap.getAddr32(0, 0)) = kBadBeef;
3461 RasterBuffer* raster_buffer = resource_provider->AcquireImageRasterBuffer(id);
3462 skia::RefPtr<SkCanvas> canvas = raster_buffer->AcquireSkCanvas();
3463 ASSERT_TRUE(!!canvas);
3464 canvas->writePixels(bitmap, 0, 0);
3465 raster_buffer->ReleaseSkCanvas(canvas);
3466 canvas.clear();
3467 resource_provider->ReleaseImageRasterBuffer(id);
3470 ResourceProvider::ScopedReadLockSoftware lock(resource_provider.get(), id);
3471 const SkBitmap* sk_bitmap = lock.sk_bitmap();
3472 EXPECT_EQ(sk_bitmap->width(), size.width());
3473 EXPECT_EQ(sk_bitmap->height(), size.height());
3474 EXPECT_EQ(*sk_bitmap->getAddr32(0, 0), kBadBeef);
3477 resource_provider->DeleteResource(id);
3480 TEST_P(ResourceProviderTest, CopyResource_GLTexture) {
3481 if (GetParam() != ResourceProvider::GLTexture)
3482 return;
3483 scoped_ptr<AllocationTrackingContext3D> context_owned(
3484 new StrictMock<AllocationTrackingContext3D>);
3485 AllocationTrackingContext3D* context = context_owned.get();
3486 context_owned->set_support_sync_query(true);
3488 FakeOutputSurfaceClient output_surface_client;
3489 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
3490 context_owned.PassAs<TestWebGraphicsContext3D>()));
3491 ASSERT_TRUE(output_surface->BindToClient(&output_surface_client));
3493 const int kWidth = 2;
3494 const int kHeight = 2;
3495 gfx::Size size(kWidth, kHeight);
3496 ResourceFormat format = RGBA_8888;
3497 ResourceProvider::ResourceId source_id = 0;
3498 ResourceProvider::ResourceId dest_id = 0;
3499 const unsigned kSourceTextureId = 123u;
3500 const unsigned kDestTextureId = 321u;
3501 const unsigned kImageId = 234u;
3503 scoped_ptr<ResourceProvider> resource_provider(
3504 ResourceProvider::Create(output_surface.get(),
3505 shared_bitmap_manager_.get(),
3506 NULL,
3508 false,
3510 false));
3512 source_id = resource_provider->CreateResource(
3513 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
3515 const int kStride = 4;
3516 void* dummy_mapped_buffer_address = NULL;
3517 EXPECT_CALL(
3518 *context,
3519 createImageCHROMIUM(kWidth, kHeight, GL_RGBA8_OES, GL_IMAGE_MAP_CHROMIUM))
3520 .WillOnce(Return(kImageId))
3521 .RetiresOnSaturation();
3522 EXPECT_CALL(
3523 *context,
3524 getImageParameterivCHROMIUM(kImageId, GL_IMAGE_ROWBYTES_CHROMIUM, _))
3525 .WillOnce(SetArgPointee<2>(kStride))
3526 .RetiresOnSaturation();
3527 EXPECT_CALL(*context, mapImageCHROMIUM(kImageId))
3528 .WillOnce(Return(dummy_mapped_buffer_address))
3529 .RetiresOnSaturation();
3530 resource_provider->AcquireImageRasterBuffer(source_id);
3531 resource_provider->ReleaseImageRasterBuffer(source_id);
3532 Mock::VerifyAndClearExpectations(context);
3534 dest_id = resource_provider->CreateResource(
3535 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
3537 EXPECT_CALL(*context, NextTextureId())
3538 .WillOnce(Return(kDestTextureId))
3539 .RetiresOnSaturation();
3540 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kDestTextureId))
3541 .Times(1)
3542 .RetiresOnSaturation();
3543 EXPECT_CALL(*context, NextTextureId())
3544 .WillOnce(Return(kSourceTextureId))
3545 .RetiresOnSaturation();
3546 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, kSourceTextureId))
3547 .Times(2)
3548 .RetiresOnSaturation();
3549 EXPECT_CALL(*context, bindTexImage2DCHROMIUM(GL_TEXTURE_2D, kImageId))
3550 .Times(1)
3551 .RetiresOnSaturation();
3552 resource_provider->CopyResource(source_id, dest_id);
3553 Mock::VerifyAndClearExpectations(context);
3555 EXPECT_CALL(*context, destroyImageCHROMIUM(kImageId))
3556 .Times(1)
3557 .RetiresOnSaturation();
3558 EXPECT_CALL(*context, RetireTextureId(kSourceTextureId))
3559 .Times(1)
3560 .RetiresOnSaturation();
3561 EXPECT_CALL(*context, RetireTextureId(kDestTextureId))
3562 .Times(1)
3563 .RetiresOnSaturation();
3564 resource_provider->DeleteResource(source_id);
3565 resource_provider->DeleteResource(dest_id);
3568 TEST_P(ResourceProviderTest, CopyResource_Bitmap) {
3569 if (GetParam() != ResourceProvider::Bitmap)
3570 return;
3571 FakeOutputSurfaceClient output_surface_client;
3572 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::CreateSoftware(
3573 make_scoped_ptr(new SoftwareOutputDevice)));
3574 CHECK(output_surface->BindToClient(&output_surface_client));
3576 gfx::Size size(1, 1);
3577 ResourceFormat format = RGBA_8888;
3578 ResourceProvider::ResourceId source_id = 0;
3579 ResourceProvider::ResourceId dest_id = 0;
3580 const uint32_t kBadBeef = 0xbadbeef;
3582 scoped_ptr<ResourceProvider> resource_provider(
3583 ResourceProvider::Create(output_surface.get(),
3584 shared_bitmap_manager_.get(),
3585 NULL,
3587 false,
3589 false));
3591 source_id = resource_provider->CreateResource(
3592 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
3594 SkBitmap bitmap;
3595 bitmap.allocN32Pixels(size.width(), size.height());
3596 *(bitmap.getAddr32(0, 0)) = kBadBeef;
3597 RasterBuffer* raster_buffer =
3598 resource_provider->AcquireImageRasterBuffer(source_id);
3599 skia::RefPtr<SkCanvas> canvas = raster_buffer->AcquireSkCanvas();
3600 ASSERT_TRUE(!!canvas);
3601 canvas->writePixels(bitmap, 0, 0);
3602 raster_buffer->ReleaseSkCanvas(canvas);
3603 canvas.clear();
3604 resource_provider->ReleaseImageRasterBuffer(source_id);
3606 dest_id = resource_provider->CreateResource(
3607 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
3609 resource_provider->CopyResource(source_id, dest_id);
3612 ResourceProvider::ScopedReadLockSoftware lock(resource_provider.get(),
3613 dest_id);
3614 const SkBitmap* sk_bitmap = lock.sk_bitmap();
3615 EXPECT_EQ(sk_bitmap->width(), size.width());
3616 EXPECT_EQ(sk_bitmap->height(), size.height());
3617 EXPECT_EQ(*sk_bitmap->getAddr32(0, 0), kBadBeef);
3620 resource_provider->DeleteResource(source_id);
3621 resource_provider->DeleteResource(dest_id);
3624 void InitializeGLAndCheck(ContextSharedData* shared_data,
3625 ResourceProvider* resource_provider,
3626 FakeOutputSurface* output_surface) {
3627 scoped_ptr<ResourceProviderContext> context_owned =
3628 ResourceProviderContext::Create(shared_data);
3629 ResourceProviderContext* context = context_owned.get();
3631 scoped_refptr<TestContextProvider> context_provider =
3632 TestContextProvider::Create(
3633 context_owned.PassAs<TestWebGraphicsContext3D>());
3634 output_surface->InitializeAndSetContext3d(context_provider);
3635 resource_provider->InitializeGL();
3637 CheckCreateResource(ResourceProvider::GLTexture, resource_provider, context);
3640 TEST(ResourceProviderTest, BasicInitializeGLSoftware) {
3641 scoped_ptr<ContextSharedData> shared_data = ContextSharedData::Create();
3642 bool delegated_rendering = false;
3643 scoped_ptr<FakeOutputSurface> output_surface(
3644 FakeOutputSurface::CreateDeferredGL(
3645 scoped_ptr<SoftwareOutputDevice>(new SoftwareOutputDevice),
3646 delegated_rendering));
3647 FakeOutputSurfaceClient client(output_surface.get());
3648 EXPECT_TRUE(output_surface->BindToClient(&client));
3649 scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
3650 new TestSharedBitmapManager());
3651 scoped_ptr<ResourceProvider> resource_provider(
3652 ResourceProvider::Create(output_surface.get(),
3653 shared_bitmap_manager.get(),
3654 NULL,
3656 false,
3658 false));
3660 CheckCreateResource(ResourceProvider::Bitmap, resource_provider.get(), NULL);
3662 InitializeGLAndCheck(shared_data.get(),
3663 resource_provider.get(),
3664 output_surface.get());
3666 resource_provider->InitializeSoftware();
3667 output_surface->ReleaseGL();
3668 CheckCreateResource(ResourceProvider::Bitmap, resource_provider.get(), NULL);
3670 InitializeGLAndCheck(shared_data.get(),
3671 resource_provider.get(),
3672 output_surface.get());
3675 TEST_P(ResourceProviderTest, CompressedTextureETC1Allocate) {
3676 if (GetParam() != ResourceProvider::GLTexture)
3677 return;
3679 scoped_ptr<AllocationTrackingContext3D> context_owned(
3680 new AllocationTrackingContext3D);
3681 AllocationTrackingContext3D* context = context_owned.get();
3682 context_owned->set_support_compressed_texture_etc1(true);
3684 FakeOutputSurfaceClient output_surface_client;
3685 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
3686 context_owned.PassAs<TestWebGraphicsContext3D>()));
3687 CHECK(output_surface->BindToClient(&output_surface_client));
3689 gfx::Size size(4, 4);
3690 scoped_ptr<ResourceProvider> resource_provider(
3691 ResourceProvider::Create(output_surface.get(),
3692 shared_bitmap_manager_.get(),
3693 NULL,
3695 false,
3697 false));
3698 int texture_id = 123;
3700 ResourceProvider::ResourceId id = resource_provider->CreateResource(
3701 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, ETC1);
3702 EXPECT_NE(0u, id);
3703 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3704 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(2);
3705 resource_provider->AllocateForTesting(id);
3707 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3708 resource_provider->DeleteResource(id);
3711 TEST_P(ResourceProviderTest, CompressedTextureETC1SetPixels) {
3712 if (GetParam() != ResourceProvider::GLTexture)
3713 return;
3715 scoped_ptr<AllocationTrackingContext3D> context_owned(
3716 new AllocationTrackingContext3D);
3717 AllocationTrackingContext3D* context = context_owned.get();
3718 context_owned->set_support_compressed_texture_etc1(true);
3720 FakeOutputSurfaceClient output_surface_client;
3721 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
3722 context_owned.PassAs<TestWebGraphicsContext3D>()));
3723 CHECK(output_surface->BindToClient(&output_surface_client));
3725 gfx::Size size(4, 4);
3726 scoped_ptr<ResourceProvider> resource_provider(
3727 ResourceProvider::Create(output_surface.get(),
3728 shared_bitmap_manager_.get(),
3729 NULL,
3731 false,
3733 false));
3734 int texture_id = 123;
3735 uint8_t pixels[8];
3737 ResourceProvider::ResourceId id = resource_provider->CreateResource(
3738 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, ETC1);
3739 EXPECT_NE(0u, id);
3740 EXPECT_CALL(*context, NextTextureId()).WillOnce(Return(texture_id));
3741 EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id)).Times(3);
3742 EXPECT_CALL(*context,
3743 compressedTexImage2D(
3744 _, 0, _, size.width(), size.height(), _, _, _)).Times(1);
3745 resource_provider->SetPixels(
3746 id, pixels, gfx::Rect(size), gfx::Rect(size), gfx::Vector2d(0, 0));
3748 EXPECT_CALL(*context, RetireTextureId(texture_id)).Times(1);
3749 resource_provider->DeleteResource(id);
3752 INSTANTIATE_TEST_CASE_P(
3753 ResourceProviderTests,
3754 ResourceProviderTest,
3755 ::testing::Values(ResourceProvider::GLTexture, ResourceProvider::Bitmap));
3757 class TextureIdAllocationTrackingContext : public TestWebGraphicsContext3D {
3758 public:
3759 virtual GLuint NextTextureId() OVERRIDE {
3760 base::AutoLock lock(namespace_->lock);
3761 return namespace_->next_texture_id++;
3763 virtual void RetireTextureId(GLuint) OVERRIDE {}
3764 GLuint PeekTextureId() {
3765 base::AutoLock lock(namespace_->lock);
3766 return namespace_->next_texture_id;
3770 TEST(ResourceProviderTest, TextureAllocationChunkSize) {
3771 scoped_ptr<TextureIdAllocationTrackingContext> context_owned(
3772 new TextureIdAllocationTrackingContext);
3773 TextureIdAllocationTrackingContext* context = context_owned.get();
3775 FakeOutputSurfaceClient output_surface_client;
3776 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
3777 context_owned.PassAs<TestWebGraphicsContext3D>()));
3778 CHECK(output_surface->BindToClient(&output_surface_client));
3779 scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
3780 new TestSharedBitmapManager());
3782 gfx::Size size(1, 1);
3783 ResourceFormat format = RGBA_8888;
3786 size_t kTextureAllocationChunkSize = 1;
3787 scoped_ptr<ResourceProvider> resource_provider(
3788 ResourceProvider::Create(output_surface.get(),
3789 shared_bitmap_manager.get(),
3790 NULL,
3792 false,
3793 kTextureAllocationChunkSize,
3794 false));
3796 ResourceProvider::ResourceId id = resource_provider->CreateResource(
3797 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
3798 resource_provider->AllocateForTesting(id);
3799 Mock::VerifyAndClearExpectations(context);
3801 DCHECK_EQ(2u, context->PeekTextureId());
3802 resource_provider->DeleteResource(id);
3806 size_t kTextureAllocationChunkSize = 8;
3807 scoped_ptr<ResourceProvider> resource_provider(
3808 ResourceProvider::Create(output_surface.get(),
3809 shared_bitmap_manager.get(),
3810 NULL,
3812 false,
3813 kTextureAllocationChunkSize,
3814 false));
3816 ResourceProvider::ResourceId id = resource_provider->CreateResource(
3817 size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureHintImmutable, format);
3818 resource_provider->AllocateForTesting(id);
3819 Mock::VerifyAndClearExpectations(context);
3821 DCHECK_EQ(10u, context->PeekTextureId());
3822 resource_provider->DeleteResource(id);
3826 } // namespace
3827 } // namespace cc