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"
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 "gpu/GLES2/gl2extchromium.h"
26 #include "testing/gmock/include/gmock/gmock.h"
27 #include "testing/gtest/include/gtest/gtest.h"
28 #include "third_party/khronos/GLES2/gl2.h"
29 #include "third_party/khronos/GLES2/gl2ext.h"
30 #include "ui/gfx/rect.h"
33 using testing::NiceMock
;
34 using testing::Return
;
35 using testing::SetArgPointee
;
36 using testing::StrictMock
;
42 static void EmptyReleaseCallback(uint32 sync_point
, bool lost_resource
) {}
44 static void SharedMemoryReleaseCallback(scoped_ptr
<base::SharedMemory
> memory
,
46 bool lost_resource
) {}
48 static void ReleaseTextureMailbox(uint32
* release_sync_point
,
49 bool* release_lost_resource
,
52 *release_sync_point
= sync_point
;
53 *release_lost_resource
= lost_resource
;
56 static void ReleaseSharedMemoryCallback(
57 scoped_ptr
<base::SharedMemory
> shared_memory
,
59 uint32
* release_sync_point
,
60 bool* lost_resource_result
,
63 *release_called
= true;
64 *release_sync_point
= sync_point
;
65 *lost_resource_result
= lost_resource
;
68 static scoped_ptr
<base::SharedMemory
> CreateAndFillSharedMemory(
69 const gfx::Size
& size
,
71 scoped_ptr
<base::SharedMemory
> shared_memory(new base::SharedMemory
);
72 CHECK(shared_memory
->CreateAndMapAnonymous(4 * size
.GetArea()));
73 uint32_t* pixels
= reinterpret_cast<uint32_t*>(shared_memory
->memory());
75 std::fill_n(pixels
, size
.GetArea(), value
);
76 return shared_memory
.Pass();
79 class TextureStateTrackingContext
: public TestWebGraphicsContext3D
{
81 MOCK_METHOD2(bindTexture
, void(GLenum target
, GLuint texture
));
82 MOCK_METHOD3(texParameteri
, void(GLenum target
, GLenum pname
, GLint param
));
83 MOCK_METHOD1(waitSyncPoint
, void(GLuint sync_point
));
84 MOCK_METHOD0(insertSyncPoint
, GLuint(void));
85 MOCK_METHOD2(produceTextureCHROMIUM
,
86 void(GLenum target
, const GLbyte
* mailbox
));
87 MOCK_METHOD2(consumeTextureCHROMIUM
,
88 void(GLenum target
, const GLbyte
* mailbox
));
90 // Force all textures to be consecutive numbers starting at "1",
91 // so we easily can test for them.
92 virtual GLuint
NextTextureId() OVERRIDE
{
93 base::AutoLock
lock(namespace_
->lock
);
94 return namespace_
->next_texture_id
++;
96 virtual void RetireTextureId(GLuint
) OVERRIDE
{}
99 // Shared data between multiple ResourceProviderContext. This contains mailbox
100 // contents as well as information about sync points.
101 class ContextSharedData
{
103 static scoped_ptr
<ContextSharedData
> Create() {
104 return make_scoped_ptr(new ContextSharedData());
107 uint32
InsertSyncPoint() { return next_sync_point_
++; }
109 void GenMailbox(GLbyte
* mailbox
) {
110 memset(mailbox
, 0, GL_MAILBOX_SIZE_CHROMIUM
);
111 memcpy(mailbox
, &next_mailbox_
, sizeof(next_mailbox_
));
115 void ProduceTexture(const GLbyte
* mailbox_name
,
117 scoped_refptr
<TestTexture
> texture
) {
118 unsigned mailbox
= 0;
119 memcpy(&mailbox
, mailbox_name
, sizeof(mailbox
));
120 ASSERT_TRUE(mailbox
&& mailbox
< next_mailbox_
);
121 textures_
[mailbox
] = texture
;
122 ASSERT_LT(sync_point_for_mailbox_
[mailbox
], sync_point
);
123 sync_point_for_mailbox_
[mailbox
] = sync_point
;
126 scoped_refptr
<TestTexture
> ConsumeTexture(const GLbyte
* mailbox_name
,
128 unsigned mailbox
= 0;
129 memcpy(&mailbox
, mailbox_name
, sizeof(mailbox
));
130 DCHECK(mailbox
&& mailbox
< next_mailbox_
);
132 // If the latest sync point the context has waited on is before the sync
133 // point for when the mailbox was set, pretend we never saw that
135 if (sync_point_for_mailbox_
[mailbox
] > sync_point
) {
137 return scoped_refptr
<TestTexture
>();
139 return textures_
[mailbox
];
143 ContextSharedData() : next_sync_point_(1), next_mailbox_(1) {}
145 uint32 next_sync_point_
;
146 unsigned next_mailbox_
;
147 typedef base::hash_map
<unsigned, scoped_refptr
<TestTexture
> > TextureMap
;
148 TextureMap textures_
;
149 base::hash_map
<unsigned, uint32
> sync_point_for_mailbox_
;
152 class ResourceProviderContext
: public TestWebGraphicsContext3D
{
154 static scoped_ptr
<ResourceProviderContext
> Create(
155 ContextSharedData
* shared_data
) {
156 return make_scoped_ptr(new ResourceProviderContext(shared_data
));
159 virtual GLuint
insertSyncPoint() OVERRIDE
{
160 uint32 sync_point
= shared_data_
->InsertSyncPoint();
161 // Commit the produceTextureCHROMIUM calls at this point, so that
162 // they're associated with the sync point.
163 for (PendingProduceTextureList::iterator it
=
164 pending_produce_textures_
.begin();
165 it
!= pending_produce_textures_
.end();
167 shared_data_
->ProduceTexture(
168 (*it
)->mailbox
, sync_point
, (*it
)->texture
);
170 pending_produce_textures_
.clear();
174 virtual void waitSyncPoint(GLuint sync_point
) OVERRIDE
{
175 last_waited_sync_point_
= std::max(sync_point
, last_waited_sync_point_
);
178 unsigned last_waited_sync_point() const { return last_waited_sync_point_
; }
180 virtual void texStorage2DEXT(GLenum target
,
182 GLuint internalformat
,
184 GLint height
) OVERRIDE
{
185 CheckTextureIsBound(target
);
186 ASSERT_EQ(static_cast<unsigned>(GL_TEXTURE_2D
), target
);
187 ASSERT_EQ(1, levels
);
188 GLenum format
= GL_RGBA
;
189 switch (internalformat
) {
193 format
= GL_BGRA_EXT
;
198 AllocateTexture(gfx::Size(width
, height
), format
);
201 virtual void texImage2D(GLenum target
,
203 GLenum internalformat
,
209 const void* pixels
) OVERRIDE
{
210 CheckTextureIsBound(target
);
211 ASSERT_EQ(static_cast<unsigned>(GL_TEXTURE_2D
), target
);
213 ASSERT_EQ(internalformat
, format
);
214 ASSERT_FALSE(border
);
215 ASSERT_EQ(static_cast<unsigned>(GL_UNSIGNED_BYTE
), type
);
216 AllocateTexture(gfx::Size(width
, height
), format
);
218 SetPixels(0, 0, width
, height
, pixels
);
221 virtual void texSubImage2D(GLenum target
,
229 const void* pixels
) OVERRIDE
{
230 CheckTextureIsBound(target
);
231 ASSERT_EQ(static_cast<unsigned>(GL_TEXTURE_2D
), target
);
233 ASSERT_EQ(static_cast<unsigned>(GL_UNSIGNED_BYTE
), type
);
235 base::AutoLock
lock_for_texture_access(namespace_
->lock
);
236 ASSERT_EQ(GLDataFormat(BoundTexture(target
)->format
), format
);
239 SetPixels(xoffset
, yoffset
, width
, height
, pixels
);
242 virtual void genMailboxCHROMIUM(GLbyte
* mailbox
) OVERRIDE
{
243 return shared_data_
->GenMailbox(mailbox
);
246 virtual void produceTextureCHROMIUM(GLenum target
,
247 const GLbyte
* mailbox
) OVERRIDE
{
248 CheckTextureIsBound(target
);
250 // Delay moving the texture into the mailbox until the next
251 // InsertSyncPoint, so that it is not visible to other contexts that
252 // haven't waited on that sync point.
253 scoped_ptr
<PendingProduceTexture
> pending(new PendingProduceTexture
);
254 memcpy(pending
->mailbox
, mailbox
, sizeof(pending
->mailbox
));
255 base::AutoLock
lock_for_texture_access(namespace_
->lock
);
256 pending
->texture
= BoundTexture(target
);
257 pending_produce_textures_
.push_back(pending
.Pass());
260 virtual void consumeTextureCHROMIUM(GLenum target
,
261 const GLbyte
* mailbox
) OVERRIDE
{
262 CheckTextureIsBound(target
);
263 base::AutoLock
lock_for_texture_access(namespace_
->lock
);
264 scoped_refptr
<TestTexture
> texture
=
265 shared_data_
->ConsumeTexture(mailbox
, last_waited_sync_point_
);
266 namespace_
->textures
.Replace(BoundTextureId(target
), texture
);
269 void GetPixels(const gfx::Size
& size
,
270 ResourceFormat format
,
272 CheckTextureIsBound(GL_TEXTURE_2D
);
273 base::AutoLock
lock_for_texture_access(namespace_
->lock
);
274 scoped_refptr
<TestTexture
> texture
= BoundTexture(GL_TEXTURE_2D
);
275 ASSERT_EQ(texture
->size
, size
);
276 ASSERT_EQ(texture
->format
, format
);
277 memcpy(pixels
, texture
->data
.get(), TextureSizeBytes(size
, format
));
281 explicit ResourceProviderContext(ContextSharedData
* shared_data
)
282 : shared_data_(shared_data
),
283 last_waited_sync_point_(0) {}
286 void AllocateTexture(const gfx::Size
& size
, GLenum format
) {
287 CheckTextureIsBound(GL_TEXTURE_2D
);
288 ResourceFormat texture_format
= RGBA_8888
;
291 texture_format
= RGBA_8888
;
294 texture_format
= BGRA_8888
;
297 base::AutoLock
lock_for_texture_access(namespace_
->lock
);
298 BoundTexture(GL_TEXTURE_2D
)->Reallocate(size
, texture_format
);
301 void SetPixels(int xoffset
,
305 const void* pixels
) {
306 CheckTextureIsBound(GL_TEXTURE_2D
);
307 base::AutoLock
lock_for_texture_access(namespace_
->lock
);
308 scoped_refptr
<TestTexture
> texture
= BoundTexture(GL_TEXTURE_2D
);
309 ASSERT_TRUE(texture
->data
.get());
310 ASSERT_TRUE(xoffset
>= 0 && xoffset
+ width
<= texture
->size
.width());
311 ASSERT_TRUE(yoffset
>= 0 && yoffset
+ height
<= texture
->size
.height());
313 size_t in_pitch
= TextureSizeBytes(gfx::Size(width
, 1), texture
->format
);
315 TextureSizeBytes(gfx::Size(texture
->size
.width(), 1), texture
->format
);
316 uint8_t* dest
= texture
->data
.get() + yoffset
* out_pitch
+
317 TextureSizeBytes(gfx::Size(xoffset
, 1), texture
->format
);
318 const uint8_t* src
= static_cast<const uint8_t*>(pixels
);
319 for (int i
= 0; i
< height
; ++i
) {
320 memcpy(dest
, src
, in_pitch
);
326 struct PendingProduceTexture
{
327 GLbyte mailbox
[GL_MAILBOX_SIZE_CHROMIUM
];
328 scoped_refptr
<TestTexture
> texture
;
330 typedef ScopedPtrDeque
<PendingProduceTexture
> PendingProduceTextureList
;
331 ContextSharedData
* shared_data_
;
332 GLuint last_waited_sync_point_
;
333 PendingProduceTextureList pending_produce_textures_
;
336 void GetResourcePixels(ResourceProvider
* resource_provider
,
337 ResourceProviderContext
* context
,
338 ResourceProvider::ResourceId id
,
339 const gfx::Size
& size
,
340 ResourceFormat format
,
342 switch (resource_provider
->default_resource_type()) {
343 case ResourceProvider::GLTexture
: {
344 ResourceProvider::ScopedReadLockGL
lock_gl(resource_provider
, id
);
345 ASSERT_NE(0U, lock_gl
.texture_id());
346 context
->bindTexture(GL_TEXTURE_2D
, lock_gl
.texture_id());
347 context
->GetPixels(size
, format
, pixels
);
350 case ResourceProvider::Bitmap
: {
351 ResourceProvider::ScopedReadLockSoftware
lock_software(resource_provider
,
354 lock_software
.sk_bitmap()->getPixels(),
355 lock_software
.sk_bitmap()->getSize());
358 case ResourceProvider::InvalidType
:
364 class ResourceProviderTest
365 : public testing::TestWithParam
<ResourceProvider::ResourceType
> {
367 ResourceProviderTest()
368 : shared_data_(ContextSharedData::Create()),
370 child_context_(NULL
) {
371 switch (GetParam()) {
372 case ResourceProvider::GLTexture
: {
373 scoped_ptr
<ResourceProviderContext
> context3d(
374 ResourceProviderContext::Create(shared_data_
.get()));
375 context3d_
= context3d
.get();
377 scoped_refptr
<TestContextProvider
> context_provider
=
378 TestContextProvider::Create(
379 context3d
.PassAs
<TestWebGraphicsContext3D
>());
381 output_surface_
= FakeOutputSurface::Create3d(context_provider
);
383 scoped_ptr
<ResourceProviderContext
> child_context_owned
=
384 ResourceProviderContext::Create(shared_data_
.get());
385 child_context_
= child_context_owned
.get();
386 child_output_surface_
= FakeOutputSurface::Create3d(
387 child_context_owned
.PassAs
<TestWebGraphicsContext3D
>());
390 case ResourceProvider::Bitmap
:
391 output_surface_
= FakeOutputSurface::CreateSoftware(
392 make_scoped_ptr(new SoftwareOutputDevice
));
393 child_output_surface_
= FakeOutputSurface::CreateSoftware(
394 make_scoped_ptr(new SoftwareOutputDevice
));
396 case ResourceProvider::InvalidType
:
400 CHECK(output_surface_
->BindToClient(&output_surface_client_
));
401 CHECK(child_output_surface_
->BindToClient(&child_output_surface_client_
));
403 shared_bitmap_manager_
.reset(new TestSharedBitmapManager());
405 resource_provider_
= ResourceProvider::Create(
406 output_surface_
.get(), shared_bitmap_manager_
.get(), 0, false, 1,
408 child_resource_provider_
= ResourceProvider::Create(
409 child_output_surface_
.get(),
410 shared_bitmap_manager_
.get(),
417 static void CollectResources(ReturnedResourceArray
* array
,
418 const ReturnedResourceArray
& returned
) {
419 array
->insert(array
->end(), returned
.begin(), returned
.end());
422 static ReturnCallback
GetReturnCallback(ReturnedResourceArray
* array
) {
423 return base::Bind(&ResourceProviderTest::CollectResources
, array
);
426 static void SetResourceFilter(ResourceProvider
* resource_provider
,
427 ResourceProvider::ResourceId id
,
429 ResourceProvider::ScopedSamplerGL
sampler(
430 resource_provider
, id
, GL_TEXTURE_2D
, filter
);
433 ResourceProviderContext
* context() { return context3d_
; }
435 ResourceProvider::ResourceId
CreateChildMailbox(uint32
* release_sync_point
,
437 bool* release_called
,
438 uint32
* sync_point
) {
439 if (GetParam() == ResourceProvider::GLTexture
) {
440 unsigned texture
= child_context_
->createTexture();
441 gpu::Mailbox gpu_mailbox
;
442 child_context_
->bindTexture(GL_TEXTURE_2D
, texture
);
443 child_context_
->genMailboxCHROMIUM(gpu_mailbox
.name
);
444 child_context_
->produceTextureCHROMIUM(GL_TEXTURE_2D
, gpu_mailbox
.name
);
445 *sync_point
= child_context_
->insertSyncPoint();
446 EXPECT_LT(0u, *sync_point
);
448 scoped_ptr
<base::SharedMemory
> shared_memory
;
449 scoped_ptr
<SingleReleaseCallback
> callback
=
450 SingleReleaseCallback::Create(base::Bind(ReleaseSharedMemoryCallback
,
451 base::Passed(&shared_memory
),
455 return child_resource_provider_
->CreateResourceFromTextureMailbox(
456 TextureMailbox(gpu_mailbox
, GL_TEXTURE_2D
, *sync_point
),
459 gfx::Size
size(64, 64);
460 scoped_ptr
<base::SharedMemory
> shared_memory(
461 CreateAndFillSharedMemory(size
, 0));
463 base::SharedMemory
* shared_memory_ptr
= shared_memory
.get();
464 scoped_ptr
<SingleReleaseCallback
> callback
=
465 SingleReleaseCallback::Create(base::Bind(ReleaseSharedMemoryCallback
,
466 base::Passed(&shared_memory
),
470 return child_resource_provider_
->CreateResourceFromTextureMailbox(
471 TextureMailbox(shared_memory_ptr
, size
), callback
.Pass());
476 scoped_ptr
<ContextSharedData
> shared_data_
;
477 ResourceProviderContext
* context3d_
;
478 ResourceProviderContext
* child_context_
;
479 FakeOutputSurfaceClient output_surface_client_
;
480 FakeOutputSurfaceClient child_output_surface_client_
;
481 scoped_ptr
<OutputSurface
> output_surface_
;
482 scoped_ptr
<OutputSurface
> child_output_surface_
;
483 scoped_ptr
<ResourceProvider
> resource_provider_
;
484 scoped_ptr
<ResourceProvider
> child_resource_provider_
;
485 scoped_ptr
<TestSharedBitmapManager
> shared_bitmap_manager_
;
488 void CheckCreateResource(ResourceProvider::ResourceType expected_default_type
,
489 ResourceProvider
* resource_provider
,
490 ResourceProviderContext
* context
) {
491 DCHECK_EQ(expected_default_type
, resource_provider
->default_resource_type());
493 gfx::Size
size(1, 1);
494 ResourceFormat format
= RGBA_8888
;
495 size_t pixel_size
= TextureSizeBytes(size
, format
);
496 ASSERT_EQ(4U, pixel_size
);
498 ResourceProvider::ResourceId id
= resource_provider
->CreateResource(
499 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureUsageAny
, format
);
500 EXPECT_EQ(1, static_cast<int>(resource_provider
->num_resources()));
501 if (expected_default_type
== ResourceProvider::GLTexture
)
502 EXPECT_EQ(0u, context
->NumTextures());
504 uint8_t data
[4] = { 1, 2, 3, 4 };
505 gfx::Rect
rect(size
);
506 resource_provider
->SetPixels(id
, data
, rect
, rect
, gfx::Vector2d());
507 if (expected_default_type
== ResourceProvider::GLTexture
)
508 EXPECT_EQ(1u, context
->NumTextures());
510 uint8_t result
[4] = { 0 };
511 GetResourcePixels(resource_provider
, context
, id
, size
, format
, result
);
512 EXPECT_EQ(0, memcmp(data
, result
, pixel_size
));
514 resource_provider
->DeleteResource(id
);
515 EXPECT_EQ(0, static_cast<int>(resource_provider
->num_resources()));
516 if (expected_default_type
== ResourceProvider::GLTexture
)
517 EXPECT_EQ(0u, context
->NumTextures());
520 TEST_P(ResourceProviderTest
, Basic
) {
521 CheckCreateResource(GetParam(), resource_provider_
.get(), context());
524 TEST_P(ResourceProviderTest
, Upload
) {
525 gfx::Size
size(2, 2);
526 ResourceFormat format
= RGBA_8888
;
527 size_t pixel_size
= TextureSizeBytes(size
, format
);
528 ASSERT_EQ(16U, pixel_size
);
530 ResourceProvider::ResourceId id
= resource_provider_
->CreateResource(
531 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureUsageAny
, format
);
533 uint8_t image
[16] = { 0 };
534 gfx::Rect
image_rect(size
);
535 resource_provider_
->SetPixels(
536 id
, image
, image_rect
, image_rect
, gfx::Vector2d());
538 for (uint8_t i
= 0; i
< pixel_size
; ++i
)
541 uint8_t result
[16] = { 0 };
543 gfx::Rect
source_rect(0, 0, 1, 1);
544 gfx::Vector2d
dest_offset(0, 0);
545 resource_provider_
->SetPixels(
546 id
, image
, image_rect
, source_rect
, dest_offset
);
548 uint8_t expected
[16] = { 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
550 resource_provider_
.get(), context(), id
, size
, format
, result
);
551 EXPECT_EQ(0, memcmp(expected
, result
, pixel_size
));
554 gfx::Rect
source_rect(0, 0, 1, 1);
555 gfx::Vector2d
dest_offset(1, 1);
556 resource_provider_
->SetPixels(
557 id
, image
, image_rect
, source_rect
, dest_offset
);
559 uint8_t expected
[16] = { 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3 };
561 resource_provider_
.get(), context(), id
, size
, format
, result
);
562 EXPECT_EQ(0, memcmp(expected
, result
, pixel_size
));
565 gfx::Rect
source_rect(1, 0, 1, 1);
566 gfx::Vector2d
dest_offset(0, 1);
567 resource_provider_
->SetPixels(
568 id
, image
, image_rect
, source_rect
, dest_offset
);
570 uint8_t expected
[16] = { 0, 1, 2, 3, 0, 0, 0, 0, 4, 5, 6, 7, 0, 1, 2, 3 };
572 resource_provider_
.get(), context(), id
, size
, format
, result
);
573 EXPECT_EQ(0, memcmp(expected
, result
, pixel_size
));
576 gfx::Rect
offset_image_rect(gfx::Point(100, 100), size
);
577 gfx::Rect
source_rect(100, 100, 1, 1);
578 gfx::Vector2d
dest_offset(1, 0);
579 resource_provider_
->SetPixels(
580 id
, image
, offset_image_rect
, source_rect
, dest_offset
);
582 uint8_t expected
[16] = { 0, 1, 2, 3, 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3 };
584 resource_provider_
.get(), context(), id
, size
, format
, result
);
585 EXPECT_EQ(0, memcmp(expected
, result
, pixel_size
));
588 resource_provider_
->DeleteResource(id
);
591 TEST_P(ResourceProviderTest
, TransferGLResources
) {
592 if (GetParam() != ResourceProvider::GLTexture
)
594 gfx::Size
size(1, 1);
595 ResourceFormat format
= RGBA_8888
;
596 size_t pixel_size
= TextureSizeBytes(size
, format
);
597 ASSERT_EQ(4U, pixel_size
);
599 ResourceProvider::ResourceId id1
= child_resource_provider_
->CreateResource(
600 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureUsageAny
, format
);
601 uint8_t data1
[4] = { 1, 2, 3, 4 };
602 gfx::Rect
rect(size
);
603 child_resource_provider_
->SetPixels(id1
, data1
, rect
, rect
, gfx::Vector2d());
605 ResourceProvider::ResourceId id2
= child_resource_provider_
->CreateResource(
606 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureUsageAny
, format
);
607 uint8_t data2
[4] = { 5, 5, 5, 5 };
608 child_resource_provider_
->SetPixels(id2
, data2
, rect
, rect
, gfx::Vector2d());
610 ResourceProvider::ResourceId id3
= child_resource_provider_
->CreateResource(
611 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureUsageAny
, format
);
612 child_resource_provider_
->MapImageRasterBuffer(id3
);
613 child_resource_provider_
->UnmapImageRasterBuffer(id3
);
615 GLuint external_texture_id
= child_context_
->createExternalTexture();
616 child_context_
->bindTexture(GL_TEXTURE_EXTERNAL_OES
, external_texture_id
);
618 gpu::Mailbox external_mailbox
;
619 child_context_
->genMailboxCHROMIUM(external_mailbox
.name
);
620 child_context_
->produceTextureCHROMIUM(GL_TEXTURE_EXTERNAL_OES
,
621 external_mailbox
.name
);
622 const GLuint external_sync_point
= child_context_
->insertSyncPoint();
623 ResourceProvider::ResourceId id4
=
624 child_resource_provider_
->CreateResourceFromTextureMailbox(
626 external_mailbox
, GL_TEXTURE_EXTERNAL_OES
, external_sync_point
),
627 SingleReleaseCallback::Create(base::Bind(&EmptyReleaseCallback
)));
629 ReturnedResourceArray returned_to_child
;
631 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
633 // Transfer some resources to the parent.
634 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
635 resource_ids_to_transfer
.push_back(id1
);
636 resource_ids_to_transfer
.push_back(id2
);
637 resource_ids_to_transfer
.push_back(id3
);
638 resource_ids_to_transfer
.push_back(id4
);
639 TransferableResourceArray list
;
640 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
642 ASSERT_EQ(4u, list
.size());
643 EXPECT_NE(0u, list
[0].mailbox_holder
.sync_point
);
644 EXPECT_NE(0u, list
[1].mailbox_holder
.sync_point
);
645 EXPECT_EQ(list
[0].mailbox_holder
.sync_point
,
646 list
[1].mailbox_holder
.sync_point
);
647 EXPECT_NE(0u, list
[2].mailbox_holder
.sync_point
);
648 EXPECT_EQ(list
[0].mailbox_holder
.sync_point
,
649 list
[2].mailbox_holder
.sync_point
);
650 EXPECT_EQ(external_sync_point
, list
[3].mailbox_holder
.sync_point
);
651 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
652 list
[0].mailbox_holder
.texture_target
);
653 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
654 list
[1].mailbox_holder
.texture_target
);
655 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
656 list
[2].mailbox_holder
.texture_target
);
657 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_EXTERNAL_OES
),
658 list
[3].mailbox_holder
.texture_target
);
659 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
660 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
661 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id3
));
662 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id4
));
663 resource_provider_
->ReceiveFromChild(child_id
, list
);
664 EXPECT_NE(list
[0].mailbox_holder
.sync_point
,
665 context3d_
->last_waited_sync_point());
667 ResourceProvider::ScopedReadLockGL
lock(resource_provider_
.get(),
670 EXPECT_EQ(list
[0].mailbox_holder
.sync_point
,
671 context3d_
->last_waited_sync_point());
672 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
673 resource_ids_to_transfer
);
676 EXPECT_EQ(4u, resource_provider_
->num_resources());
677 ResourceProvider::ResourceIdMap resource_map
=
678 resource_provider_
->GetChildToParentMap(child_id
);
679 ResourceProvider::ResourceId mapped_id1
= resource_map
[id1
];
680 ResourceProvider::ResourceId mapped_id2
= resource_map
[id2
];
681 ResourceProvider::ResourceId mapped_id3
= resource_map
[id3
];
682 ResourceProvider::ResourceId mapped_id4
= resource_map
[id4
];
683 EXPECT_NE(0u, mapped_id1
);
684 EXPECT_NE(0u, mapped_id2
);
685 EXPECT_NE(0u, mapped_id3
);
686 EXPECT_NE(0u, mapped_id4
);
687 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id1
));
688 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id2
));
689 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id3
));
690 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id4
));
692 uint8_t result
[4] = { 0 };
694 resource_provider_
.get(), context(), mapped_id1
, size
, format
, result
);
695 EXPECT_EQ(0, memcmp(data1
, result
, pixel_size
));
698 resource_provider_
.get(), context(), mapped_id2
, size
, format
, result
);
699 EXPECT_EQ(0, memcmp(data2
, result
, pixel_size
));
702 // Check that transfering again the same resource from the child to the
704 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
705 resource_ids_to_transfer
.push_back(id1
);
706 resource_ids_to_transfer
.push_back(id2
);
707 resource_ids_to_transfer
.push_back(id3
);
708 TransferableResourceArray list
;
709 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
711 EXPECT_EQ(3u, list
.size());
712 EXPECT_EQ(id1
, list
[0].id
);
713 EXPECT_EQ(id2
, list
[1].id
);
714 EXPECT_EQ(id3
, list
[2].id
);
715 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
716 list
[0].mailbox_holder
.texture_target
);
717 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
718 list
[1].mailbox_holder
.texture_target
);
719 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
720 list
[2].mailbox_holder
.texture_target
);
721 ReturnedResourceArray returned
;
722 TransferableResource::ReturnResources(list
, &returned
);
723 child_resource_provider_
->ReceiveReturnsFromParent(returned
);
724 // ids were exported twice, we returned them only once, they should still
726 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
727 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
728 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id3
));
731 EXPECT_EQ(0u, returned_to_child
.size());
733 // Transfer resources back from the parent to the child. Set no resources as
735 ResourceProvider::ResourceIdArray no_resources
;
736 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
738 ASSERT_EQ(4u, returned_to_child
.size());
739 EXPECT_NE(0u, returned_to_child
[0].sync_point
);
740 EXPECT_NE(0u, returned_to_child
[1].sync_point
);
741 EXPECT_NE(0u, returned_to_child
[2].sync_point
);
742 EXPECT_NE(0u, returned_to_child
[3].sync_point
);
743 EXPECT_FALSE(returned_to_child
[0].lost
);
744 EXPECT_FALSE(returned_to_child
[1].lost
);
745 EXPECT_FALSE(returned_to_child
[2].lost
);
746 EXPECT_FALSE(returned_to_child
[3].lost
);
747 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
748 returned_to_child
.clear();
750 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id1
));
751 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id2
));
752 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id3
));
753 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id4
));
756 ResourceProvider::ScopedReadLockGL
lock(child_resource_provider_
.get(),
758 ASSERT_NE(0U, lock
.texture_id());
759 child_context_
->bindTexture(GL_TEXTURE_2D
, lock
.texture_id());
760 child_context_
->GetPixels(size
, format
, result
);
761 EXPECT_EQ(0, memcmp(data1
, result
, pixel_size
));
764 ResourceProvider::ScopedReadLockGL
lock(child_resource_provider_
.get(),
766 ASSERT_NE(0U, lock
.texture_id());
767 child_context_
->bindTexture(GL_TEXTURE_2D
, lock
.texture_id());
768 child_context_
->GetPixels(size
, format
, result
);
769 EXPECT_EQ(0, memcmp(data2
, result
, pixel_size
));
772 ResourceProvider::ScopedReadLockGL
lock(child_resource_provider_
.get(),
774 ASSERT_NE(0U, lock
.texture_id());
775 child_context_
->bindTexture(GL_TEXTURE_2D
, lock
.texture_id());
778 // Transfer resources to the parent again.
779 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
780 resource_ids_to_transfer
.push_back(id1
);
781 resource_ids_to_transfer
.push_back(id2
);
782 resource_ids_to_transfer
.push_back(id3
);
783 resource_ids_to_transfer
.push_back(id4
);
784 TransferableResourceArray list
;
785 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
787 ASSERT_EQ(4u, list
.size());
788 EXPECT_EQ(id1
, list
[0].id
);
789 EXPECT_EQ(id2
, list
[1].id
);
790 EXPECT_EQ(id3
, list
[2].id
);
791 EXPECT_EQ(id4
, list
[3].id
);
792 EXPECT_NE(0u, list
[0].mailbox_holder
.sync_point
);
793 EXPECT_NE(0u, list
[1].mailbox_holder
.sync_point
);
794 EXPECT_NE(0u, list
[2].mailbox_holder
.sync_point
);
795 EXPECT_NE(0u, list
[3].mailbox_holder
.sync_point
);
796 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
797 list
[0].mailbox_holder
.texture_target
);
798 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
799 list
[1].mailbox_holder
.texture_target
);
800 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
801 list
[2].mailbox_holder
.texture_target
);
802 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_EXTERNAL_OES
),
803 list
[3].mailbox_holder
.texture_target
);
804 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
805 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
806 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id3
));
807 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id4
));
808 resource_provider_
->ReceiveFromChild(child_id
, list
);
809 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
810 resource_ids_to_transfer
);
813 EXPECT_EQ(0u, returned_to_child
.size());
815 EXPECT_EQ(4u, resource_provider_
->num_resources());
816 resource_provider_
->DestroyChild(child_id
);
817 EXPECT_EQ(0u, resource_provider_
->num_resources());
819 ASSERT_EQ(4u, returned_to_child
.size());
820 EXPECT_NE(0u, returned_to_child
[0].sync_point
);
821 EXPECT_NE(0u, returned_to_child
[1].sync_point
);
822 EXPECT_NE(0u, returned_to_child
[2].sync_point
);
823 EXPECT_NE(0u, returned_to_child
[3].sync_point
);
824 EXPECT_FALSE(returned_to_child
[0].lost
);
825 EXPECT_FALSE(returned_to_child
[1].lost
);
826 EXPECT_FALSE(returned_to_child
[2].lost
);
827 EXPECT_FALSE(returned_to_child
[3].lost
);
830 TEST_P(ResourceProviderTest
, ReadLockCountStopsReturnToChildOrDelete
) {
831 if (GetParam() != ResourceProvider::GLTexture
)
833 gfx::Size
size(1, 1);
834 ResourceFormat format
= RGBA_8888
;
836 ResourceProvider::ResourceId id1
= child_resource_provider_
->CreateResource(
837 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureUsageAny
, format
);
838 uint8_t data1
[4] = {1, 2, 3, 4};
839 gfx::Rect
rect(size
);
840 child_resource_provider_
->SetPixels(id1
, data1
, rect
, rect
, gfx::Vector2d());
842 ReturnedResourceArray returned_to_child
;
844 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
846 // Transfer some resources to the parent.
847 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
848 resource_ids_to_transfer
.push_back(id1
);
849 TransferableResourceArray list
;
850 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
852 ASSERT_EQ(1u, list
.size());
853 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
855 resource_provider_
->ReceiveFromChild(child_id
, list
);
857 ResourceProvider::ScopedReadLockGL
lock(resource_provider_
.get(),
860 resource_provider_
->DeclareUsedResourcesFromChild(
861 child_id
, ResourceProvider::ResourceIdArray());
862 EXPECT_EQ(0u, returned_to_child
.size());
865 EXPECT_EQ(1u, returned_to_child
.size());
866 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
869 ResourceProvider::ScopedReadLockGL
lock(child_resource_provider_
.get(),
871 child_resource_provider_
->DeleteResource(id1
);
872 EXPECT_EQ(1u, child_resource_provider_
->num_resources());
873 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
876 EXPECT_EQ(0u, child_resource_provider_
->num_resources());
877 resource_provider_
->DestroyChild(child_id
);
880 TEST_P(ResourceProviderTest
, TransferSoftwareResources
) {
881 if (GetParam() != ResourceProvider::Bitmap
)
884 gfx::Size
size(1, 1);
885 ResourceFormat format
= RGBA_8888
;
886 size_t pixel_size
= TextureSizeBytes(size
, format
);
887 ASSERT_EQ(4U, pixel_size
);
889 ResourceProvider::ResourceId id1
= child_resource_provider_
->CreateResource(
890 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureUsageAny
, format
);
891 uint8_t data1
[4] = { 1, 2, 3, 4 };
892 gfx::Rect
rect(size
);
893 child_resource_provider_
->SetPixels(id1
, data1
, rect
, rect
, gfx::Vector2d());
895 ResourceProvider::ResourceId id2
= child_resource_provider_
->CreateResource(
896 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureUsageAny
, format
);
897 uint8_t data2
[4] = { 5, 5, 5, 5 };
898 child_resource_provider_
->SetPixels(id2
, data2
, rect
, rect
, gfx::Vector2d());
900 ResourceProvider::ResourceId id3
= child_resource_provider_
->CreateResource(
901 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureUsageAny
, format
);
902 uint8_t data3
[4] = { 6, 7, 8, 9 };
903 SkImageInfo info
= SkImageInfo::MakeN32Premul(size
.width(), size
.height());
904 SkCanvas
* raster_canvas
= child_resource_provider_
->MapImageRasterBuffer(id3
);
905 raster_canvas
->writePixels(info
, data3
, info
.minRowBytes(), 0, 0);
906 child_resource_provider_
->UnmapImageRasterBuffer(id3
);
908 scoped_ptr
<base::SharedMemory
> shared_memory(new base::SharedMemory());
909 shared_memory
->CreateAndMapAnonymous(1);
910 base::SharedMemory
* shared_memory_ptr
= shared_memory
.get();
911 ResourceProvider::ResourceId id4
=
912 child_resource_provider_
->CreateResourceFromTextureMailbox(
913 TextureMailbox(shared_memory_ptr
, gfx::Size(1, 1)),
914 SingleReleaseCallback::Create(base::Bind(
915 &SharedMemoryReleaseCallback
, base::Passed(&shared_memory
))));
917 ReturnedResourceArray returned_to_child
;
919 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
921 // Transfer some resources to the parent.
922 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
923 resource_ids_to_transfer
.push_back(id1
);
924 resource_ids_to_transfer
.push_back(id2
);
925 resource_ids_to_transfer
.push_back(id3
);
926 resource_ids_to_transfer
.push_back(id4
);
927 TransferableResourceArray list
;
928 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
930 ASSERT_EQ(4u, list
.size());
931 EXPECT_EQ(0u, list
[0].mailbox_holder
.sync_point
);
932 EXPECT_EQ(0u, list
[1].mailbox_holder
.sync_point
);
933 EXPECT_EQ(0u, list
[2].mailbox_holder
.sync_point
);
934 EXPECT_EQ(0u, list
[3].mailbox_holder
.sync_point
);
935 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
936 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
937 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id3
));
938 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id4
));
939 resource_provider_
->ReceiveFromChild(child_id
, list
);
940 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
941 resource_ids_to_transfer
);
944 EXPECT_EQ(4u, resource_provider_
->num_resources());
945 ResourceProvider::ResourceIdMap resource_map
=
946 resource_provider_
->GetChildToParentMap(child_id
);
947 ResourceProvider::ResourceId mapped_id1
= resource_map
[id1
];
948 ResourceProvider::ResourceId mapped_id2
= resource_map
[id2
];
949 ResourceProvider::ResourceId mapped_id3
= resource_map
[id3
];
950 ResourceProvider::ResourceId mapped_id4
= resource_map
[id4
];
951 EXPECT_NE(0u, mapped_id1
);
952 EXPECT_NE(0u, mapped_id2
);
953 EXPECT_NE(0u, mapped_id3
);
954 EXPECT_NE(0u, mapped_id4
);
955 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id1
));
956 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id2
));
957 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id3
));
958 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id4
));
960 uint8_t result
[4] = { 0 };
962 resource_provider_
.get(), context(), mapped_id1
, size
, format
, result
);
963 EXPECT_EQ(0, memcmp(data1
, result
, pixel_size
));
966 resource_provider_
.get(), context(), mapped_id2
, size
, format
, result
);
967 EXPECT_EQ(0, memcmp(data2
, result
, pixel_size
));
970 resource_provider_
.get(), context(), mapped_id3
, size
, format
, result
);
971 EXPECT_EQ(0, memcmp(data3
, result
, pixel_size
));
974 // Check that transfering again the same resource from the child to the
976 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
977 resource_ids_to_transfer
.push_back(id1
);
978 resource_ids_to_transfer
.push_back(id2
);
979 resource_ids_to_transfer
.push_back(id3
);
980 TransferableResourceArray list
;
981 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
983 EXPECT_EQ(3u, list
.size());
984 EXPECT_EQ(id1
, list
[0].id
);
985 EXPECT_EQ(id2
, list
[1].id
);
986 EXPECT_EQ(id3
, list
[2].id
);
987 ReturnedResourceArray returned
;
988 TransferableResource::ReturnResources(list
, &returned
);
989 child_resource_provider_
->ReceiveReturnsFromParent(returned
);
990 // ids were exported twice, we returned them only once, they should still
992 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
993 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
994 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id3
));
997 EXPECT_EQ(0u, returned_to_child
.size());
999 // Transfer resources back from the parent to the child. Set no resources as
1001 ResourceProvider::ResourceIdArray no_resources
;
1002 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
1004 ASSERT_EQ(4u, returned_to_child
.size());
1005 EXPECT_EQ(0u, returned_to_child
[0].sync_point
);
1006 EXPECT_EQ(0u, returned_to_child
[1].sync_point
);
1007 EXPECT_EQ(0u, returned_to_child
[2].sync_point
);
1008 EXPECT_EQ(0u, returned_to_child
[3].sync_point
);
1009 std::set
<ResourceProvider::ResourceId
> expected_ids
;
1010 expected_ids
.insert(id1
);
1011 expected_ids
.insert(id2
);
1012 expected_ids
.insert(id3
);
1013 expected_ids
.insert(id4
);
1014 std::set
<ResourceProvider::ResourceId
> returned_ids
;
1015 for (unsigned i
= 0; i
< 4; i
++)
1016 returned_ids
.insert(returned_to_child
[i
].id
);
1017 EXPECT_EQ(expected_ids
, returned_ids
);
1018 EXPECT_FALSE(returned_to_child
[0].lost
);
1019 EXPECT_FALSE(returned_to_child
[1].lost
);
1020 EXPECT_FALSE(returned_to_child
[2].lost
);
1021 EXPECT_FALSE(returned_to_child
[3].lost
);
1022 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
1023 returned_to_child
.clear();
1025 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id1
));
1026 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id2
));
1027 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id3
));
1028 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id4
));
1031 ResourceProvider::ScopedReadLockSoftware
lock(
1032 child_resource_provider_
.get(), id1
);
1033 const SkBitmap
* sk_bitmap
= lock
.sk_bitmap();
1034 EXPECT_EQ(sk_bitmap
->width(), size
.width());
1035 EXPECT_EQ(sk_bitmap
->height(), size
.height());
1036 EXPECT_EQ(0, memcmp(data1
, sk_bitmap
->getPixels(), pixel_size
));
1039 ResourceProvider::ScopedReadLockSoftware
lock(
1040 child_resource_provider_
.get(), id2
);
1041 const SkBitmap
* sk_bitmap
= lock
.sk_bitmap();
1042 EXPECT_EQ(sk_bitmap
->width(), size
.width());
1043 EXPECT_EQ(sk_bitmap
->height(), size
.height());
1044 EXPECT_EQ(0, memcmp(data2
, sk_bitmap
->getPixels(), pixel_size
));
1047 ResourceProvider::ScopedReadLockSoftware
lock(
1048 child_resource_provider_
.get(), id3
);
1049 const SkBitmap
* sk_bitmap
= lock
.sk_bitmap();
1050 EXPECT_EQ(sk_bitmap
->width(), size
.width());
1051 EXPECT_EQ(sk_bitmap
->height(), size
.height());
1052 EXPECT_EQ(0, memcmp(data3
, sk_bitmap
->getPixels(), pixel_size
));
1055 // Transfer resources to the parent again.
1056 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1057 resource_ids_to_transfer
.push_back(id1
);
1058 resource_ids_to_transfer
.push_back(id2
);
1059 resource_ids_to_transfer
.push_back(id3
);
1060 resource_ids_to_transfer
.push_back(id4
);
1061 TransferableResourceArray list
;
1062 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1064 ASSERT_EQ(4u, list
.size());
1065 EXPECT_EQ(id1
, list
[0].id
);
1066 EXPECT_EQ(id2
, list
[1].id
);
1067 EXPECT_EQ(id3
, list
[2].id
);
1068 EXPECT_EQ(id4
, list
[3].id
);
1069 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
1070 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
1071 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id3
));
1072 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id4
));
1073 resource_provider_
->ReceiveFromChild(child_id
, list
);
1074 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
1075 resource_ids_to_transfer
);
1078 EXPECT_EQ(0u, returned_to_child
.size());
1080 EXPECT_EQ(4u, resource_provider_
->num_resources());
1081 resource_provider_
->DestroyChild(child_id
);
1082 EXPECT_EQ(0u, resource_provider_
->num_resources());
1084 ASSERT_EQ(4u, returned_to_child
.size());
1085 EXPECT_EQ(0u, returned_to_child
[0].sync_point
);
1086 EXPECT_EQ(0u, returned_to_child
[1].sync_point
);
1087 EXPECT_EQ(0u, returned_to_child
[2].sync_point
);
1088 EXPECT_EQ(0u, returned_to_child
[3].sync_point
);
1089 std::set
<ResourceProvider::ResourceId
> expected_ids
;
1090 expected_ids
.insert(id1
);
1091 expected_ids
.insert(id2
);
1092 expected_ids
.insert(id3
);
1093 expected_ids
.insert(id4
);
1094 std::set
<ResourceProvider::ResourceId
> returned_ids
;
1095 for (unsigned i
= 0; i
< 4; i
++)
1096 returned_ids
.insert(returned_to_child
[i
].id
);
1097 EXPECT_EQ(expected_ids
, returned_ids
);
1098 EXPECT_FALSE(returned_to_child
[0].lost
);
1099 EXPECT_FALSE(returned_to_child
[1].lost
);
1100 EXPECT_FALSE(returned_to_child
[2].lost
);
1101 EXPECT_FALSE(returned_to_child
[3].lost
);
1104 TEST_P(ResourceProviderTest
, TransferGLToSoftware
) {
1105 if (GetParam() != ResourceProvider::Bitmap
)
1108 scoped_ptr
<ResourceProviderContext
> child_context_owned(
1109 ResourceProviderContext::Create(shared_data_
.get()));
1111 FakeOutputSurfaceClient child_output_surface_client
;
1112 scoped_ptr
<OutputSurface
> child_output_surface(FakeOutputSurface::Create3d(
1113 child_context_owned
.PassAs
<TestWebGraphicsContext3D
>()));
1114 CHECK(child_output_surface
->BindToClient(&child_output_surface_client
));
1116 scoped_ptr
<ResourceProvider
> child_resource_provider(ResourceProvider::Create(
1117 child_output_surface
.get(), shared_bitmap_manager_
.get(), 0, false, 1,
1120 gfx::Size
size(1, 1);
1121 ResourceFormat format
= RGBA_8888
;
1122 size_t pixel_size
= TextureSizeBytes(size
, format
);
1123 ASSERT_EQ(4U, pixel_size
);
1125 ResourceProvider::ResourceId id1
= child_resource_provider
->CreateResource(
1126 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureUsageAny
, format
);
1127 uint8_t data1
[4] = { 1, 2, 3, 4 };
1128 gfx::Rect
rect(size
);
1129 child_resource_provider
->SetPixels(id1
, data1
, rect
, rect
, gfx::Vector2d());
1131 ReturnedResourceArray returned_to_child
;
1133 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1135 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1136 resource_ids_to_transfer
.push_back(id1
);
1137 TransferableResourceArray list
;
1138 child_resource_provider
->PrepareSendToParent(resource_ids_to_transfer
,
1140 ASSERT_EQ(1u, list
.size());
1141 EXPECT_NE(0u, list
[0].mailbox_holder
.sync_point
);
1142 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
1143 list
[0].mailbox_holder
.texture_target
);
1144 EXPECT_TRUE(child_resource_provider
->InUseByConsumer(id1
));
1145 resource_provider_
->ReceiveFromChild(child_id
, list
);
1148 EXPECT_EQ(0u, resource_provider_
->num_resources());
1149 ASSERT_EQ(1u, returned_to_child
.size());
1150 EXPECT_EQ(returned_to_child
[0].id
, id1
);
1151 ResourceProvider::ResourceIdMap resource_map
=
1152 resource_provider_
->GetChildToParentMap(child_id
);
1153 ResourceProvider::ResourceId mapped_id1
= resource_map
[id1
];
1154 EXPECT_EQ(0u, mapped_id1
);
1156 resource_provider_
->DestroyChild(child_id
);
1157 EXPECT_EQ(0u, resource_provider_
->num_resources());
1159 ASSERT_EQ(1u, returned_to_child
.size());
1160 EXPECT_FALSE(returned_to_child
[0].lost
);
1163 TEST_P(ResourceProviderTest
, TransferInvalidSoftware
) {
1164 if (GetParam() != ResourceProvider::Bitmap
)
1167 gfx::Size
size(1, 1);
1168 ResourceFormat format
= RGBA_8888
;
1169 size_t pixel_size
= TextureSizeBytes(size
, format
);
1170 ASSERT_EQ(4U, pixel_size
);
1172 ResourceProvider::ResourceId id1
= child_resource_provider_
->CreateResource(
1173 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureUsageAny
, format
);
1174 uint8_t data1
[4] = { 1, 2, 3, 4 };
1175 gfx::Rect
rect(size
);
1176 child_resource_provider_
->SetPixels(id1
, data1
, rect
, rect
, gfx::Vector2d());
1178 ReturnedResourceArray returned_to_child
;
1180 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1182 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1183 resource_ids_to_transfer
.push_back(id1
);
1184 TransferableResourceArray list
;
1185 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1187 ASSERT_EQ(1u, list
.size());
1189 list
[0].mailbox_holder
.mailbox
.name
[1] = 5;
1190 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
1191 resource_provider_
->ReceiveFromChild(child_id
, list
);
1194 EXPECT_EQ(1u, resource_provider_
->num_resources());
1195 EXPECT_EQ(0u, returned_to_child
.size());
1197 ResourceProvider::ResourceIdMap resource_map
=
1198 resource_provider_
->GetChildToParentMap(child_id
);
1199 ResourceProvider::ResourceId mapped_id1
= resource_map
[id1
];
1200 EXPECT_NE(0u, mapped_id1
);
1202 ResourceProvider::ScopedReadLockSoftware
lock(resource_provider_
.get(),
1204 EXPECT_FALSE(lock
.valid());
1207 resource_provider_
->DestroyChild(child_id
);
1208 EXPECT_EQ(0u, resource_provider_
->num_resources());
1210 ASSERT_EQ(1u, returned_to_child
.size());
1211 EXPECT_FALSE(returned_to_child
[0].lost
);
1214 TEST_P(ResourceProviderTest
, DeleteExportedResources
) {
1215 gfx::Size
size(1, 1);
1216 ResourceFormat format
= RGBA_8888
;
1217 size_t pixel_size
= TextureSizeBytes(size
, format
);
1218 ASSERT_EQ(4U, pixel_size
);
1220 ResourceProvider::ResourceId id1
= child_resource_provider_
->CreateResource(
1221 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureUsageAny
, format
);
1222 uint8_t data1
[4] = { 1, 2, 3, 4 };
1223 gfx::Rect
rect(size
);
1224 child_resource_provider_
->SetPixels(id1
, data1
, rect
, rect
, gfx::Vector2d());
1226 ResourceProvider::ResourceId id2
= child_resource_provider_
->CreateResource(
1227 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureUsageAny
, format
);
1228 uint8_t data2
[4] = {5, 5, 5, 5};
1229 child_resource_provider_
->SetPixels(id2
, data2
, rect
, rect
, gfx::Vector2d());
1231 ReturnedResourceArray returned_to_child
;
1233 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1235 // Transfer some resources to the parent.
1236 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1237 resource_ids_to_transfer
.push_back(id1
);
1238 resource_ids_to_transfer
.push_back(id2
);
1239 TransferableResourceArray list
;
1240 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1242 ASSERT_EQ(2u, list
.size());
1243 if (GetParam() == ResourceProvider::GLTexture
) {
1244 EXPECT_NE(0u, list
[0].mailbox_holder
.sync_point
);
1245 EXPECT_NE(0u, list
[1].mailbox_holder
.sync_point
);
1247 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
1248 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
1249 resource_provider_
->ReceiveFromChild(child_id
, list
);
1250 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
1251 resource_ids_to_transfer
);
1254 EXPECT_EQ(2u, resource_provider_
->num_resources());
1255 ResourceProvider::ResourceIdMap resource_map
=
1256 resource_provider_
->GetChildToParentMap(child_id
);
1257 ResourceProvider::ResourceId mapped_id1
= resource_map
[id1
];
1258 ResourceProvider::ResourceId mapped_id2
= resource_map
[id2
];
1259 EXPECT_NE(0u, mapped_id1
);
1260 EXPECT_NE(0u, mapped_id2
);
1261 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id1
));
1262 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id2
));
1265 // The parent transfers the resources to the grandparent.
1266 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1267 resource_ids_to_transfer
.push_back(mapped_id1
);
1268 resource_ids_to_transfer
.push_back(mapped_id2
);
1269 TransferableResourceArray list
;
1270 resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
, &list
);
1272 ASSERT_EQ(2u, list
.size());
1273 if (GetParam() == ResourceProvider::GLTexture
) {
1274 EXPECT_NE(0u, list
[0].mailbox_holder
.sync_point
);
1275 EXPECT_NE(0u, list
[1].mailbox_holder
.sync_point
);
1277 EXPECT_TRUE(resource_provider_
->InUseByConsumer(id1
));
1278 EXPECT_TRUE(resource_provider_
->InUseByConsumer(id2
));
1280 // Release the resource in the parent. Set no resources as being in use. The
1281 // resources are exported so that can't be transferred back yet.
1282 ResourceProvider::ResourceIdArray no_resources
;
1283 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
1285 EXPECT_EQ(0u, returned_to_child
.size());
1286 EXPECT_EQ(2u, resource_provider_
->num_resources());
1288 // Return the resources from the grandparent to the parent. They should be
1289 // returned to the child then.
1290 EXPECT_EQ(2u, list
.size());
1291 EXPECT_EQ(mapped_id1
, list
[0].id
);
1292 EXPECT_EQ(mapped_id2
, list
[1].id
);
1293 ReturnedResourceArray returned
;
1294 TransferableResource::ReturnResources(list
, &returned
);
1295 resource_provider_
->ReceiveReturnsFromParent(returned
);
1297 EXPECT_EQ(0u, resource_provider_
->num_resources());
1298 ASSERT_EQ(2u, returned_to_child
.size());
1299 if (GetParam() == ResourceProvider::GLTexture
) {
1300 EXPECT_NE(0u, returned_to_child
[0].sync_point
);
1301 EXPECT_NE(0u, returned_to_child
[1].sync_point
);
1303 EXPECT_FALSE(returned_to_child
[0].lost
);
1304 EXPECT_FALSE(returned_to_child
[1].lost
);
1308 TEST_P(ResourceProviderTest
, DestroyChildWithExportedResources
) {
1309 gfx::Size
size(1, 1);
1310 ResourceFormat format
= RGBA_8888
;
1311 size_t pixel_size
= TextureSizeBytes(size
, format
);
1312 ASSERT_EQ(4U, pixel_size
);
1314 ResourceProvider::ResourceId id1
= child_resource_provider_
->CreateResource(
1315 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureUsageAny
, format
);
1316 uint8_t data1
[4] = {1, 2, 3, 4};
1317 gfx::Rect
rect(size
);
1318 child_resource_provider_
->SetPixels(id1
, data1
, rect
, rect
, gfx::Vector2d());
1320 ResourceProvider::ResourceId id2
= child_resource_provider_
->CreateResource(
1321 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureUsageAny
, format
);
1322 uint8_t data2
[4] = {5, 5, 5, 5};
1323 child_resource_provider_
->SetPixels(id2
, data2
, rect
, rect
, gfx::Vector2d());
1325 ReturnedResourceArray returned_to_child
;
1327 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1329 // Transfer some resources to the parent.
1330 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1331 resource_ids_to_transfer
.push_back(id1
);
1332 resource_ids_to_transfer
.push_back(id2
);
1333 TransferableResourceArray list
;
1334 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1336 ASSERT_EQ(2u, list
.size());
1337 if (GetParam() == ResourceProvider::GLTexture
) {
1338 EXPECT_NE(0u, list
[0].mailbox_holder
.sync_point
);
1339 EXPECT_NE(0u, list
[1].mailbox_holder
.sync_point
);
1341 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
1342 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
1343 resource_provider_
->ReceiveFromChild(child_id
, list
);
1344 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
1345 resource_ids_to_transfer
);
1348 EXPECT_EQ(2u, resource_provider_
->num_resources());
1349 ResourceProvider::ResourceIdMap resource_map
=
1350 resource_provider_
->GetChildToParentMap(child_id
);
1351 ResourceProvider::ResourceId mapped_id1
= resource_map
[id1
];
1352 ResourceProvider::ResourceId mapped_id2
= resource_map
[id2
];
1353 EXPECT_NE(0u, mapped_id1
);
1354 EXPECT_NE(0u, mapped_id2
);
1355 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id1
));
1356 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id2
));
1359 // The parent transfers the resources to the grandparent.
1360 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1361 resource_ids_to_transfer
.push_back(mapped_id1
);
1362 resource_ids_to_transfer
.push_back(mapped_id2
);
1363 TransferableResourceArray list
;
1364 resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
, &list
);
1366 ASSERT_EQ(2u, list
.size());
1367 if (GetParam() == ResourceProvider::GLTexture
) {
1368 EXPECT_NE(0u, list
[0].mailbox_holder
.sync_point
);
1369 EXPECT_NE(0u, list
[1].mailbox_holder
.sync_point
);
1371 EXPECT_TRUE(resource_provider_
->InUseByConsumer(id1
));
1372 EXPECT_TRUE(resource_provider_
->InUseByConsumer(id2
));
1374 // Release the resource in the parent. Set no resources as being in use. The
1375 // resources are exported so that can't be transferred back yet.
1376 ResourceProvider::ResourceIdArray no_resources
;
1377 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
1379 // Destroy the child, the resources should not be returned yet.
1380 EXPECT_EQ(0u, returned_to_child
.size());
1381 EXPECT_EQ(2u, resource_provider_
->num_resources());
1383 resource_provider_
->DestroyChild(child_id
);
1385 EXPECT_EQ(2u, resource_provider_
->num_resources());
1386 ASSERT_EQ(0u, returned_to_child
.size());
1388 // Return a resource from the grandparent, it should be returned at this
1390 EXPECT_EQ(2u, list
.size());
1391 EXPECT_EQ(mapped_id1
, list
[0].id
);
1392 EXPECT_EQ(mapped_id2
, list
[1].id
);
1393 TransferableResourceArray return_list
;
1394 return_list
.push_back(list
[1]);
1396 ReturnedResourceArray returned
;
1397 TransferableResource::ReturnResources(return_list
, &returned
);
1398 resource_provider_
->ReceiveReturnsFromParent(returned
);
1400 EXPECT_EQ(1u, resource_provider_
->num_resources());
1401 ASSERT_EQ(1u, returned_to_child
.size());
1402 if (GetParam() == ResourceProvider::GLTexture
) {
1403 EXPECT_NE(0u, returned_to_child
[0].sync_point
);
1405 EXPECT_FALSE(returned_to_child
[0].lost
);
1406 returned_to_child
.clear();
1408 // Destroy the parent resource provider. The resource that's left should be
1409 // lost at this point, and returned.
1410 resource_provider_
.reset();
1411 ASSERT_EQ(1u, returned_to_child
.size());
1412 if (GetParam() == ResourceProvider::GLTexture
) {
1413 EXPECT_NE(0u, returned_to_child
[0].sync_point
);
1415 EXPECT_TRUE(returned_to_child
[0].lost
);
1419 TEST_P(ResourceProviderTest
, DeleteTransferredResources
) {
1420 gfx::Size
size(1, 1);
1421 ResourceFormat format
= RGBA_8888
;
1422 size_t pixel_size
= TextureSizeBytes(size
, format
);
1423 ASSERT_EQ(4U, pixel_size
);
1425 ResourceProvider::ResourceId id
= child_resource_provider_
->CreateResource(
1426 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureUsageAny
, format
);
1427 uint8_t data
[4] = { 1, 2, 3, 4 };
1428 gfx::Rect
rect(size
);
1429 child_resource_provider_
->SetPixels(id
, data
, rect
, rect
, gfx::Vector2d());
1431 ReturnedResourceArray returned_to_child
;
1433 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1435 // Transfer some resource to the parent.
1436 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1437 resource_ids_to_transfer
.push_back(id
);
1438 TransferableResourceArray list
;
1439 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1441 ASSERT_EQ(1u, list
.size());
1442 if (GetParam() == ResourceProvider::GLTexture
)
1443 EXPECT_NE(0u, list
[0].mailbox_holder
.sync_point
);
1444 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id
));
1445 resource_provider_
->ReceiveFromChild(child_id
, list
);
1446 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
1447 resource_ids_to_transfer
);
1450 // Delete textures in the child, while they are transfered.
1451 child_resource_provider_
->DeleteResource(id
);
1452 EXPECT_EQ(1u, child_resource_provider_
->num_resources());
1454 EXPECT_EQ(0u, returned_to_child
.size());
1456 // Transfer resources back from the parent to the child. Set no resources as
1458 ResourceProvider::ResourceIdArray no_resources
;
1459 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
1461 ASSERT_EQ(1u, returned_to_child
.size());
1462 if (GetParam() == ResourceProvider::GLTexture
)
1463 EXPECT_NE(0u, returned_to_child
[0].sync_point
);
1464 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
1466 EXPECT_EQ(0u, child_resource_provider_
->num_resources());
1469 TEST_P(ResourceProviderTest
, UnuseTransferredResources
) {
1470 gfx::Size
size(1, 1);
1471 ResourceFormat format
= RGBA_8888
;
1472 size_t pixel_size
= TextureSizeBytes(size
, format
);
1473 ASSERT_EQ(4U, pixel_size
);
1475 ResourceProvider::ResourceId id
= child_resource_provider_
->CreateResource(
1476 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureUsageAny
, format
);
1477 uint8_t data
[4] = {1, 2, 3, 4};
1478 gfx::Rect
rect(size
);
1479 child_resource_provider_
->SetPixels(id
, data
, rect
, rect
, gfx::Vector2d());
1481 ReturnedResourceArray returned_to_child
;
1483 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1484 const ResourceProvider::ResourceIdMap
& map
=
1485 resource_provider_
->GetChildToParentMap(child_id
);
1487 // Transfer some resource to the parent.
1488 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1489 resource_ids_to_transfer
.push_back(id
);
1490 TransferableResourceArray list
;
1491 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1493 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id
));
1494 resource_provider_
->ReceiveFromChild(child_id
, list
);
1495 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
1496 resource_ids_to_transfer
);
1498 TransferableResourceArray sent_to_top_level
;
1500 // Parent transfers to top-level.
1501 ASSERT_TRUE(map
.find(id
) != map
.end());
1502 ResourceProvider::ResourceId parent_id
= map
.find(id
)->second
;
1503 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1504 resource_ids_to_transfer
.push_back(parent_id
);
1505 resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1506 &sent_to_top_level
);
1507 EXPECT_TRUE(resource_provider_
->InUseByConsumer(parent_id
));
1510 // Stop using resource.
1511 ResourceProvider::ResourceIdArray empty
;
1512 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, empty
);
1513 // Resource is not yet returned to the child, since it's in use by the
1515 EXPECT_TRUE(returned_to_child
.empty());
1518 // Send the resource to the parent again.
1519 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1520 resource_ids_to_transfer
.push_back(id
);
1521 TransferableResourceArray list
;
1522 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1524 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id
));
1525 resource_provider_
->ReceiveFromChild(child_id
, list
);
1526 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
1527 resource_ids_to_transfer
);
1530 // Receive returns back from top-level.
1531 ReturnedResourceArray returned
;
1532 TransferableResource::ReturnResources(sent_to_top_level
, &returned
);
1533 resource_provider_
->ReceiveReturnsFromParent(returned
);
1534 // Resource is still not yet returned to the child, since it's declared used
1536 EXPECT_TRUE(returned_to_child
.empty());
1537 ASSERT_TRUE(map
.find(id
) != map
.end());
1538 ResourceProvider::ResourceId parent_id
= map
.find(id
)->second
;
1539 EXPECT_FALSE(resource_provider_
->InUseByConsumer(parent_id
));
1542 sent_to_top_level
.clear();
1543 // Parent transfers again to top-level.
1544 ASSERT_TRUE(map
.find(id
) != map
.end());
1545 ResourceProvider::ResourceId parent_id
= map
.find(id
)->second
;
1546 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1547 resource_ids_to_transfer
.push_back(parent_id
);
1548 resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1549 &sent_to_top_level
);
1550 EXPECT_TRUE(resource_provider_
->InUseByConsumer(parent_id
));
1553 // Receive returns back from top-level.
1554 ReturnedResourceArray returned
;
1555 TransferableResource::ReturnResources(sent_to_top_level
, &returned
);
1556 resource_provider_
->ReceiveReturnsFromParent(returned
);
1557 // Resource is still not yet returned to the child, since it's still
1558 // declared used in the parent.
1559 EXPECT_TRUE(returned_to_child
.empty());
1560 ASSERT_TRUE(map
.find(id
) != map
.end());
1561 ResourceProvider::ResourceId parent_id
= map
.find(id
)->second
;
1562 EXPECT_FALSE(resource_provider_
->InUseByConsumer(parent_id
));
1565 // Stop using resource.
1566 ResourceProvider::ResourceIdArray empty
;
1567 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, empty
);
1568 // Resource should have been returned to the child, since it's no longer in
1569 // use by the top-level.
1570 ASSERT_EQ(1u, returned_to_child
.size());
1571 EXPECT_EQ(id
, returned_to_child
[0].id
);
1572 EXPECT_EQ(2, returned_to_child
[0].count
);
1573 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
1574 returned_to_child
.clear();
1575 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id
));
1579 class ResourceProviderTestTextureFilters
: public ResourceProviderTest
{
1581 static void RunTest(GLenum child_filter
, GLenum parent_filter
) {
1582 scoped_ptr
<TextureStateTrackingContext
> child_context_owned(
1583 new TextureStateTrackingContext
);
1584 TextureStateTrackingContext
* child_context
= child_context_owned
.get();
1586 FakeOutputSurfaceClient child_output_surface_client
;
1587 scoped_ptr
<OutputSurface
> child_output_surface(FakeOutputSurface::Create3d(
1588 child_context_owned
.PassAs
<TestWebGraphicsContext3D
>()));
1589 CHECK(child_output_surface
->BindToClient(&child_output_surface_client
));
1590 scoped_ptr
<SharedBitmapManager
> shared_bitmap_manager(
1591 new TestSharedBitmapManager());
1593 scoped_ptr
<ResourceProvider
> child_resource_provider(
1594 ResourceProvider::Create(child_output_surface
.get(),
1595 shared_bitmap_manager
.get(),
1601 scoped_ptr
<TextureStateTrackingContext
> parent_context_owned(
1602 new TextureStateTrackingContext
);
1603 TextureStateTrackingContext
* parent_context
= parent_context_owned
.get();
1605 FakeOutputSurfaceClient parent_output_surface_client
;
1606 scoped_ptr
<OutputSurface
> parent_output_surface(FakeOutputSurface::Create3d(
1607 parent_context_owned
.PassAs
<TestWebGraphicsContext3D
>()));
1608 CHECK(parent_output_surface
->BindToClient(&parent_output_surface_client
));
1610 scoped_ptr
<ResourceProvider
> parent_resource_provider(
1611 ResourceProvider::Create(parent_output_surface
.get(),
1612 shared_bitmap_manager
.get(),
1618 gfx::Size
size(1, 1);
1619 ResourceFormat format
= RGBA_8888
;
1620 int child_texture_id
= 1;
1621 int parent_texture_id
= 2;
1623 size_t pixel_size
= TextureSizeBytes(size
, format
);
1624 ASSERT_EQ(4U, pixel_size
);
1626 ResourceProvider::ResourceId id
= child_resource_provider
->CreateResource(
1627 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureUsageAny
, format
);
1629 // The new texture is created with GL_LINEAR.
1630 EXPECT_CALL(*child_context
, bindTexture(GL_TEXTURE_2D
, child_texture_id
))
1631 .Times(2); // Once to create and once to allocate.
1632 EXPECT_CALL(*child_context
,
1633 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
));
1634 EXPECT_CALL(*child_context
,
1635 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
));
1638 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
));
1641 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
));
1642 EXPECT_CALL(*child_context
,
1643 texParameteri(GL_TEXTURE_2D
,
1644 GL_TEXTURE_POOL_CHROMIUM
,
1645 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
));
1646 child_resource_provider
->AllocateForTesting(id
);
1647 Mock::VerifyAndClearExpectations(child_context
);
1649 uint8_t data
[4] = { 1, 2, 3, 4 };
1650 gfx::Rect
rect(size
);
1652 EXPECT_CALL(*child_context
, bindTexture(GL_TEXTURE_2D
, child_texture_id
));
1653 child_resource_provider
->SetPixels(id
, data
, rect
, rect
, gfx::Vector2d());
1654 Mock::VerifyAndClearExpectations(child_context
);
1656 // The texture is set to |child_filter| in the child.
1657 EXPECT_CALL(*child_context
, bindTexture(GL_TEXTURE_2D
, child_texture_id
));
1658 if (child_filter
!= GL_LINEAR
) {
1661 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, child_filter
));
1664 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, child_filter
));
1666 SetResourceFilter(child_resource_provider
.get(), id
, child_filter
);
1667 Mock::VerifyAndClearExpectations(child_context
);
1669 ReturnedResourceArray returned_to_child
;
1670 int child_id
= parent_resource_provider
->CreateChild(
1671 GetReturnCallback(&returned_to_child
));
1673 // Transfer some resource to the parent.
1674 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1675 resource_ids_to_transfer
.push_back(id
);
1676 TransferableResourceArray list
;
1678 EXPECT_CALL(*child_context
, bindTexture(GL_TEXTURE_2D
, child_texture_id
));
1679 EXPECT_CALL(*child_context
,
1680 produceTextureCHROMIUM(GL_TEXTURE_2D
, _
));
1681 EXPECT_CALL(*child_context
, insertSyncPoint());
1682 child_resource_provider
->PrepareSendToParent(resource_ids_to_transfer
,
1684 Mock::VerifyAndClearExpectations(child_context
);
1686 ASSERT_EQ(1u, list
.size());
1687 EXPECT_EQ(static_cast<unsigned>(child_filter
), list
[0].filter
);
1689 EXPECT_CALL(*parent_context
,
1690 bindTexture(GL_TEXTURE_2D
, parent_texture_id
));
1691 EXPECT_CALL(*parent_context
, consumeTextureCHROMIUM(GL_TEXTURE_2D
, _
));
1692 parent_resource_provider
->ReceiveFromChild(child_id
, list
);
1694 ResourceProvider::ScopedReadLockGL
lock(parent_resource_provider
.get(),
1697 Mock::VerifyAndClearExpectations(parent_context
);
1699 parent_resource_provider
->DeclareUsedResourcesFromChild(
1700 child_id
, resource_ids_to_transfer
);
1701 Mock::VerifyAndClearExpectations(parent_context
);
1703 ResourceProvider::ResourceIdMap resource_map
=
1704 parent_resource_provider
->GetChildToParentMap(child_id
);
1705 ResourceProvider::ResourceId mapped_id
= resource_map
[id
];
1706 EXPECT_NE(0u, mapped_id
);
1708 // The texture is set to |parent_filter| in the parent.
1709 EXPECT_CALL(*parent_context
, bindTexture(GL_TEXTURE_2D
, parent_texture_id
));
1712 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, parent_filter
));
1715 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, parent_filter
));
1716 SetResourceFilter(parent_resource_provider
.get(), mapped_id
, parent_filter
);
1717 Mock::VerifyAndClearExpectations(parent_context
);
1719 // The texture should be reset to |child_filter| in the parent when it is
1720 // returned, since that is how it was received.
1721 EXPECT_CALL(*parent_context
, bindTexture(GL_TEXTURE_2D
, parent_texture_id
));
1724 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, child_filter
));
1727 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, child_filter
));
1730 EXPECT_EQ(0u, returned_to_child
.size());
1732 // Transfer resources back from the parent to the child. Set no resources
1734 ResourceProvider::ResourceIdArray no_resources
;
1735 EXPECT_CALL(*parent_context
, insertSyncPoint());
1736 parent_resource_provider
->DeclareUsedResourcesFromChild(child_id
,
1738 Mock::VerifyAndClearExpectations(parent_context
);
1740 ASSERT_EQ(1u, returned_to_child
.size());
1741 child_resource_provider
->ReceiveReturnsFromParent(returned_to_child
);
1744 // The child remembers the texture filter is set to |child_filter|.
1745 EXPECT_CALL(*child_context
, bindTexture(GL_TEXTURE_2D
, child_texture_id
));
1746 SetResourceFilter(child_resource_provider
.get(), id
, child_filter
);
1747 Mock::VerifyAndClearExpectations(child_context
);
1751 TEST_P(ResourceProviderTest
, TextureFilters_ChildNearestParentLinear
) {
1752 if (GetParam() != ResourceProvider::GLTexture
)
1754 ResourceProviderTestTextureFilters::RunTest(GL_NEAREST
, GL_LINEAR
);
1757 TEST_P(ResourceProviderTest
, TextureFilters_ChildLinearParentNearest
) {
1758 if (GetParam() != ResourceProvider::GLTexture
)
1760 ResourceProviderTestTextureFilters::RunTest(GL_LINEAR
, GL_NEAREST
);
1763 TEST_P(ResourceProviderTest
, TransferMailboxResources
) {
1764 // Other mailbox transfers tested elsewhere.
1765 if (GetParam() != ResourceProvider::GLTexture
)
1767 unsigned texture
= context()->createTexture();
1768 context()->bindTexture(GL_TEXTURE_2D
, texture
);
1769 uint8_t data
[4] = { 1, 2, 3, 4 };
1770 context()->texImage2D(
1771 GL_TEXTURE_2D
, 0, GL_RGBA
, 1, 1, 0, GL_RGBA
, GL_UNSIGNED_BYTE
, &data
);
1772 gpu::Mailbox mailbox
;
1773 context()->genMailboxCHROMIUM(mailbox
.name
);
1774 context()->produceTextureCHROMIUM(GL_TEXTURE_2D
, mailbox
.name
);
1775 uint32 sync_point
= context()->insertSyncPoint();
1777 // All the logic below assumes that the sync points are all positive.
1778 EXPECT_LT(0u, sync_point
);
1780 uint32 release_sync_point
= 0;
1781 bool lost_resource
= false;
1782 ReleaseCallback callback
=
1783 base::Bind(ReleaseTextureMailbox
, &release_sync_point
, &lost_resource
);
1784 ResourceProvider::ResourceId resource
=
1785 resource_provider_
->CreateResourceFromTextureMailbox(
1786 TextureMailbox(mailbox
, GL_TEXTURE_2D
, sync_point
),
1787 SingleReleaseCallback::Create(callback
));
1788 EXPECT_EQ(1u, context()->NumTextures());
1789 EXPECT_EQ(0u, release_sync_point
);
1791 // Transfer the resource, expect the sync points to be consistent.
1792 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1793 resource_ids_to_transfer
.push_back(resource
);
1794 TransferableResourceArray list
;
1795 resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
, &list
);
1796 ASSERT_EQ(1u, list
.size());
1797 EXPECT_LE(sync_point
, list
[0].mailbox_holder
.sync_point
);
1799 memcmp(mailbox
.name
,
1800 list
[0].mailbox_holder
.mailbox
.name
,
1801 sizeof(mailbox
.name
)));
1802 EXPECT_EQ(0u, release_sync_point
);
1804 context()->waitSyncPoint(list
[0].mailbox_holder
.sync_point
);
1805 unsigned other_texture
= context()->createTexture();
1806 context()->bindTexture(GL_TEXTURE_2D
, other_texture
);
1807 context()->consumeTextureCHROMIUM(GL_TEXTURE_2D
, mailbox
.name
);
1808 uint8_t test_data
[4] = { 0 };
1809 context()->GetPixels(
1810 gfx::Size(1, 1), RGBA_8888
, test_data
);
1811 EXPECT_EQ(0, memcmp(data
, test_data
, sizeof(data
)));
1812 context()->produceTextureCHROMIUM(GL_TEXTURE_2D
, mailbox
.name
);
1813 context()->deleteTexture(other_texture
);
1814 list
[0].mailbox_holder
.sync_point
= context()->insertSyncPoint();
1815 EXPECT_LT(0u, list
[0].mailbox_holder
.sync_point
);
1817 // Receive the resource, then delete it, expect the sync points to be
1819 ReturnedResourceArray returned
;
1820 TransferableResource::ReturnResources(list
, &returned
);
1821 resource_provider_
->ReceiveReturnsFromParent(returned
);
1822 EXPECT_EQ(1u, context()->NumTextures());
1823 EXPECT_EQ(0u, release_sync_point
);
1825 resource_provider_
->DeleteResource(resource
);
1826 EXPECT_LE(list
[0].mailbox_holder
.sync_point
, release_sync_point
);
1827 EXPECT_FALSE(lost_resource
);
1830 // We're going to do the same thing as above, but testing the case where we
1831 // delete the resource before we receive it back.
1832 sync_point
= release_sync_point
;
1833 EXPECT_LT(0u, sync_point
);
1834 release_sync_point
= 0;
1835 resource
= resource_provider_
->CreateResourceFromTextureMailbox(
1836 TextureMailbox(mailbox
, GL_TEXTURE_2D
, sync_point
),
1837 SingleReleaseCallback::Create(callback
));
1838 EXPECT_EQ(1u, context()->NumTextures());
1839 EXPECT_EQ(0u, release_sync_point
);
1841 // Transfer the resource, expect the sync points to be consistent.
1842 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1843 resource_ids_to_transfer
.push_back(resource
);
1844 TransferableResourceArray list
;
1845 resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
, &list
);
1846 ASSERT_EQ(1u, list
.size());
1847 EXPECT_LE(sync_point
, list
[0].mailbox_holder
.sync_point
);
1849 memcmp(mailbox
.name
,
1850 list
[0].mailbox_holder
.mailbox
.name
,
1851 sizeof(mailbox
.name
)));
1852 EXPECT_EQ(0u, release_sync_point
);
1854 context()->waitSyncPoint(list
[0].mailbox_holder
.sync_point
);
1855 unsigned other_texture
= context()->createTexture();
1856 context()->bindTexture(GL_TEXTURE_2D
, other_texture
);
1857 context()->consumeTextureCHROMIUM(GL_TEXTURE_2D
, mailbox
.name
);
1858 uint8_t test_data
[4] = { 0 };
1859 context()->GetPixels(
1860 gfx::Size(1, 1), RGBA_8888
, test_data
);
1861 EXPECT_EQ(0, memcmp(data
, test_data
, sizeof(data
)));
1862 context()->produceTextureCHROMIUM(GL_TEXTURE_2D
, mailbox
.name
);
1863 context()->deleteTexture(other_texture
);
1864 list
[0].mailbox_holder
.sync_point
= context()->insertSyncPoint();
1865 EXPECT_LT(0u, list
[0].mailbox_holder
.sync_point
);
1867 // Delete the resource, which shouldn't do anything.
1868 resource_provider_
->DeleteResource(resource
);
1869 EXPECT_EQ(1u, context()->NumTextures());
1870 EXPECT_EQ(0u, release_sync_point
);
1872 // Then receive the resource which should release the mailbox, expect the
1873 // sync points to be consistent.
1874 ReturnedResourceArray returned
;
1875 TransferableResource::ReturnResources(list
, &returned
);
1876 resource_provider_
->ReceiveReturnsFromParent(returned
);
1877 EXPECT_LE(list
[0].mailbox_holder
.sync_point
, release_sync_point
);
1878 EXPECT_FALSE(lost_resource
);
1881 context()->waitSyncPoint(release_sync_point
);
1882 context()->bindTexture(GL_TEXTURE_2D
, texture
);
1883 context()->consumeTextureCHROMIUM(GL_TEXTURE_2D
, mailbox
.name
);
1884 context()->deleteTexture(texture
);
1887 TEST_P(ResourceProviderTest
, LostResourceInParent
) {
1888 gfx::Size
size(1, 1);
1889 ResourceFormat format
= RGBA_8888
;
1890 ResourceProvider::ResourceId resource
=
1891 child_resource_provider_
->CreateResource(
1892 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureUsageAny
, format
);
1893 child_resource_provider_
->AllocateForTesting(resource
);
1894 // Expect a GL resource to be lost.
1895 bool should_lose_resource
= GetParam() == ResourceProvider::GLTexture
;
1897 ReturnedResourceArray returned_to_child
;
1899 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1901 // Transfer the resource to the parent.
1902 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1903 resource_ids_to_transfer
.push_back(resource
);
1904 TransferableResourceArray list
;
1905 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1907 EXPECT_EQ(1u, list
.size());
1909 resource_provider_
->ReceiveFromChild(child_id
, list
);
1910 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
1911 resource_ids_to_transfer
);
1914 // Lose the output surface in the parent.
1915 resource_provider_
->DidLoseOutputSurface();
1918 EXPECT_EQ(0u, returned_to_child
.size());
1920 // Transfer resources back from the parent to the child. Set no resources as
1922 ResourceProvider::ResourceIdArray no_resources
;
1923 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
1925 // Expect a GL resource to be lost.
1926 ASSERT_EQ(1u, returned_to_child
.size());
1927 EXPECT_EQ(should_lose_resource
, returned_to_child
[0].lost
);
1928 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
1929 returned_to_child
.clear();
1932 // A GL resource should be lost.
1933 EXPECT_EQ(should_lose_resource
, child_resource_provider_
->IsLost(resource
));
1935 // Lost resources stay in use in the parent forever.
1936 EXPECT_EQ(should_lose_resource
,
1937 child_resource_provider_
->InUseByConsumer(resource
));
1940 TEST_P(ResourceProviderTest
, LostResourceInGrandParent
) {
1941 gfx::Size
size(1, 1);
1942 ResourceFormat format
= RGBA_8888
;
1943 ResourceProvider::ResourceId resource
=
1944 child_resource_provider_
->CreateResource(
1945 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureUsageAny
, format
);
1946 child_resource_provider_
->AllocateForTesting(resource
);
1948 ReturnedResourceArray returned_to_child
;
1950 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1952 // Transfer the resource to the parent.
1953 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1954 resource_ids_to_transfer
.push_back(resource
);
1955 TransferableResourceArray list
;
1956 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1958 EXPECT_EQ(1u, list
.size());
1960 resource_provider_
->ReceiveFromChild(child_id
, list
);
1961 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
1962 resource_ids_to_transfer
);
1966 ResourceProvider::ResourceIdMap resource_map
=
1967 resource_provider_
->GetChildToParentMap(child_id
);
1968 ResourceProvider::ResourceId parent_resource
= resource_map
[resource
];
1969 EXPECT_NE(0u, parent_resource
);
1971 // Transfer to a grandparent.
1972 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1973 resource_ids_to_transfer
.push_back(parent_resource
);
1974 TransferableResourceArray list
;
1975 resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
, &list
);
1977 // Receive back a lost resource from the grandparent.
1978 EXPECT_EQ(1u, list
.size());
1979 EXPECT_EQ(parent_resource
, list
[0].id
);
1980 ReturnedResourceArray returned
;
1981 TransferableResource::ReturnResources(list
, &returned
);
1982 EXPECT_EQ(1u, returned
.size());
1983 EXPECT_EQ(parent_resource
, returned
[0].id
);
1984 returned
[0].lost
= true;
1985 resource_provider_
->ReceiveReturnsFromParent(returned
);
1987 // The resource should be lost.
1988 EXPECT_TRUE(resource_provider_
->IsLost(parent_resource
));
1990 // Lost resources stay in use in the parent forever.
1991 EXPECT_TRUE(resource_provider_
->InUseByConsumer(parent_resource
));
1995 EXPECT_EQ(0u, returned_to_child
.size());
1997 // Transfer resources back from the parent to the child. Set no resources as
1999 ResourceProvider::ResourceIdArray no_resources
;
2000 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
2002 // Expect the resource to be lost.
2003 ASSERT_EQ(1u, returned_to_child
.size());
2004 EXPECT_TRUE(returned_to_child
[0].lost
);
2005 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
2006 returned_to_child
.clear();
2009 // The resource should be lost.
2010 EXPECT_TRUE(child_resource_provider_
->IsLost(resource
));
2012 // Lost resources stay in use in the parent forever.
2013 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(resource
));
2016 TEST_P(ResourceProviderTest
, LostMailboxInParent
) {
2017 uint32 release_sync_point
= 0;
2018 bool lost_resource
= false;
2019 bool release_called
= false;
2020 uint32 sync_point
= 0;
2021 ResourceProvider::ResourceId resource
= CreateChildMailbox(
2022 &release_sync_point
, &lost_resource
, &release_called
, &sync_point
);
2024 ReturnedResourceArray returned_to_child
;
2026 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
2028 // Transfer the resource to the parent.
2029 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
2030 resource_ids_to_transfer
.push_back(resource
);
2031 TransferableResourceArray list
;
2032 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
2034 EXPECT_EQ(1u, list
.size());
2036 resource_provider_
->ReceiveFromChild(child_id
, list
);
2037 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
2038 resource_ids_to_transfer
);
2041 // Lose the output surface in the parent.
2042 resource_provider_
->DidLoseOutputSurface();
2045 EXPECT_EQ(0u, returned_to_child
.size());
2047 // Transfer resources back from the parent to the child. Set no resources as
2049 ResourceProvider::ResourceIdArray no_resources
;
2050 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
2052 ASSERT_EQ(1u, returned_to_child
.size());
2053 // Losing an output surface only loses hardware resources.
2054 EXPECT_EQ(returned_to_child
[0].lost
,
2055 GetParam() == ResourceProvider::GLTexture
);
2056 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
2057 returned_to_child
.clear();
2060 // Delete the resource in the child. Expect the resource to be lost if it's
2062 child_resource_provider_
->DeleteResource(resource
);
2063 EXPECT_EQ(lost_resource
, GetParam() == ResourceProvider::GLTexture
);
2066 TEST_P(ResourceProviderTest
, LostMailboxInGrandParent
) {
2067 uint32 release_sync_point
= 0;
2068 bool lost_resource
= false;
2069 bool release_called
= false;
2070 uint32 sync_point
= 0;
2071 ResourceProvider::ResourceId resource
= CreateChildMailbox(
2072 &release_sync_point
, &lost_resource
, &release_called
, &sync_point
);
2074 ReturnedResourceArray returned_to_child
;
2076 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
2078 // Transfer the resource to the parent.
2079 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
2080 resource_ids_to_transfer
.push_back(resource
);
2081 TransferableResourceArray list
;
2082 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
2084 EXPECT_EQ(1u, list
.size());
2086 resource_provider_
->ReceiveFromChild(child_id
, list
);
2087 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
2088 resource_ids_to_transfer
);
2092 ResourceProvider::ResourceIdMap resource_map
=
2093 resource_provider_
->GetChildToParentMap(child_id
);
2094 ResourceProvider::ResourceId parent_resource
= resource_map
[resource
];
2095 EXPECT_NE(0u, parent_resource
);
2097 // Transfer to a grandparent.
2098 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
2099 resource_ids_to_transfer
.push_back(parent_resource
);
2100 TransferableResourceArray list
;
2101 resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
, &list
);
2103 // Receive back a lost resource from the grandparent.
2104 EXPECT_EQ(1u, list
.size());
2105 EXPECT_EQ(parent_resource
, list
[0].id
);
2106 ReturnedResourceArray returned
;
2107 TransferableResource::ReturnResources(list
, &returned
);
2108 EXPECT_EQ(1u, returned
.size());
2109 EXPECT_EQ(parent_resource
, returned
[0].id
);
2110 returned
[0].lost
= true;
2111 resource_provider_
->ReceiveReturnsFromParent(returned
);
2115 EXPECT_EQ(0u, returned_to_child
.size());
2117 // Transfer resources back from the parent to the child. Set no resources as
2119 ResourceProvider::ResourceIdArray no_resources
;
2120 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
2122 // Expect the resource to be lost.
2123 ASSERT_EQ(1u, returned_to_child
.size());
2124 EXPECT_TRUE(returned_to_child
[0].lost
);
2125 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
2126 returned_to_child
.clear();
2129 // Delete the resource in the child. Expect the resource to be lost.
2130 child_resource_provider_
->DeleteResource(resource
);
2131 EXPECT_TRUE(lost_resource
);
2134 TEST_P(ResourceProviderTest
, Shutdown
) {
2135 uint32 release_sync_point
= 0;
2136 bool lost_resource
= false;
2137 bool release_called
= false;
2138 uint32 sync_point
= 0;
2140 &release_sync_point
, &lost_resource
, &release_called
, &sync_point
);
2142 EXPECT_EQ(0u, release_sync_point
);
2143 EXPECT_FALSE(lost_resource
);
2145 child_resource_provider_
.reset();
2147 if (GetParam() == ResourceProvider::GLTexture
) {
2148 EXPECT_LE(sync_point
, release_sync_point
);
2150 EXPECT_TRUE(release_called
);
2151 EXPECT_FALSE(lost_resource
);
2154 TEST_P(ResourceProviderTest
, ShutdownWithExportedResource
) {
2155 uint32 release_sync_point
= 0;
2156 bool lost_resource
= false;
2157 bool release_called
= false;
2158 uint32 sync_point
= 0;
2159 ResourceProvider::ResourceId resource
= CreateChildMailbox(
2160 &release_sync_point
, &lost_resource
, &release_called
, &sync_point
);
2162 // Transfer the resource, so we can't release it properly on shutdown.
2163 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
2164 resource_ids_to_transfer
.push_back(resource
);
2165 TransferableResourceArray list
;
2166 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
2169 EXPECT_EQ(0u, release_sync_point
);
2170 EXPECT_FALSE(lost_resource
);
2172 child_resource_provider_
.reset();
2174 // Since the resource is in the parent, the child considers it lost.
2175 EXPECT_EQ(0u, release_sync_point
);
2176 EXPECT_TRUE(lost_resource
);
2179 TEST_P(ResourceProviderTest
, LostContext
) {
2180 // TextureMailbox callbacks only exist for GL textures for now.
2181 if (GetParam() != ResourceProvider::GLTexture
)
2183 unsigned texture
= context()->createTexture();
2184 context()->bindTexture(GL_TEXTURE_2D
, texture
);
2185 gpu::Mailbox mailbox
;
2186 context()->genMailboxCHROMIUM(mailbox
.name
);
2187 context()->produceTextureCHROMIUM(GL_TEXTURE_2D
, mailbox
.name
);
2188 uint32 sync_point
= context()->insertSyncPoint();
2190 EXPECT_LT(0u, sync_point
);
2192 uint32 release_sync_point
= 0;
2193 bool lost_resource
= false;
2194 scoped_ptr
<SingleReleaseCallback
> callback
= SingleReleaseCallback::Create(
2195 base::Bind(ReleaseTextureMailbox
, &release_sync_point
, &lost_resource
));
2196 resource_provider_
->CreateResourceFromTextureMailbox(
2197 TextureMailbox(mailbox
, GL_TEXTURE_2D
, sync_point
), callback
.Pass());
2199 EXPECT_EQ(0u, release_sync_point
);
2200 EXPECT_FALSE(lost_resource
);
2202 resource_provider_
->DidLoseOutputSurface();
2203 resource_provider_
.reset();
2205 EXPECT_LE(sync_point
, release_sync_point
);
2206 EXPECT_TRUE(lost_resource
);
2209 TEST_P(ResourceProviderTest
, ScopedSampler
) {
2210 // Sampling is only supported for GL textures.
2211 if (GetParam() != ResourceProvider::GLTexture
)
2214 scoped_ptr
<TextureStateTrackingContext
> context_owned(
2215 new TextureStateTrackingContext
);
2216 TextureStateTrackingContext
* context
= context_owned
.get();
2218 FakeOutputSurfaceClient output_surface_client
;
2219 scoped_ptr
<OutputSurface
> output_surface(FakeOutputSurface::Create3d(
2220 context_owned
.PassAs
<TestWebGraphicsContext3D
>()));
2221 CHECK(output_surface
->BindToClient(&output_surface_client
));
2223 scoped_ptr
<ResourceProvider
> resource_provider(ResourceProvider::Create(
2224 output_surface
.get(), shared_bitmap_manager_
.get(), 0, false, 1, false));
2226 gfx::Size
size(1, 1);
2227 ResourceFormat format
= RGBA_8888
;
2230 ResourceProvider::ResourceId id
= resource_provider
->CreateResource(
2231 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureUsageAny
, format
);
2233 // Check that the texture gets created with the right sampler settings.
2234 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
))
2235 .Times(2); // Once to create and once to allocate.
2236 EXPECT_CALL(*context
,
2237 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
));
2238 EXPECT_CALL(*context
,
2239 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
));
2242 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
));
2245 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
));
2246 EXPECT_CALL(*context
,
2247 texParameteri(GL_TEXTURE_2D
,
2248 GL_TEXTURE_POOL_CHROMIUM
,
2249 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
));
2251 resource_provider
->AllocateForTesting(id
);
2252 Mock::VerifyAndClearExpectations(context
);
2254 // Creating a sampler with the default filter should not change any texture
2257 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
));
2258 ResourceProvider::ScopedSamplerGL
sampler(
2259 resource_provider
.get(), id
, GL_TEXTURE_2D
, GL_LINEAR
);
2260 Mock::VerifyAndClearExpectations(context
);
2263 // Using a different filter should be reflected in the texture parameters.
2265 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
));
2268 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
));
2271 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
));
2272 ResourceProvider::ScopedSamplerGL
sampler(
2273 resource_provider
.get(), id
, GL_TEXTURE_2D
, GL_NEAREST
);
2274 Mock::VerifyAndClearExpectations(context
);
2277 // Test resetting to the default filter.
2279 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
));
2280 EXPECT_CALL(*context
,
2281 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
));
2282 EXPECT_CALL(*context
,
2283 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
));
2284 ResourceProvider::ScopedSamplerGL
sampler(
2285 resource_provider
.get(), id
, GL_TEXTURE_2D
, GL_LINEAR
);
2286 Mock::VerifyAndClearExpectations(context
);
2290 TEST_P(ResourceProviderTest
, ManagedResource
) {
2291 // Sampling is only supported for GL textures.
2292 if (GetParam() != ResourceProvider::GLTexture
)
2295 scoped_ptr
<TextureStateTrackingContext
> context_owned(
2296 new TextureStateTrackingContext
);
2297 TextureStateTrackingContext
* context
= context_owned
.get();
2299 FakeOutputSurfaceClient output_surface_client
;
2300 scoped_ptr
<OutputSurface
> output_surface(FakeOutputSurface::Create3d(
2301 context_owned
.PassAs
<TestWebGraphicsContext3D
>()));
2302 CHECK(output_surface
->BindToClient(&output_surface_client
));
2304 scoped_ptr
<ResourceProvider
> resource_provider(ResourceProvider::Create(
2305 output_surface
.get(), shared_bitmap_manager_
.get(), 0, false, 1, false));
2307 gfx::Size
size(1, 1);
2308 ResourceFormat format
= RGBA_8888
;
2311 // Check that the texture gets created with the right sampler settings.
2312 ResourceProvider::ResourceId id
= resource_provider
->CreateManagedResource(
2316 ResourceProvider::TextureUsageAny
,
2318 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
));
2319 EXPECT_CALL(*context
,
2320 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
));
2321 EXPECT_CALL(*context
,
2322 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
));
2325 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
));
2328 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
));
2329 EXPECT_CALL(*context
,
2330 texParameteri(GL_TEXTURE_2D
,
2331 GL_TEXTURE_POOL_CHROMIUM
,
2332 GL_TEXTURE_POOL_MANAGED_CHROMIUM
));
2333 resource_provider
->CreateForTesting(id
);
2336 Mock::VerifyAndClearExpectations(context
);
2339 TEST_P(ResourceProviderTest
, TextureWrapMode
) {
2340 // Sampling is only supported for GL textures.
2341 if (GetParam() != ResourceProvider::GLTexture
)
2344 scoped_ptr
<TextureStateTrackingContext
> context_owned(
2345 new TextureStateTrackingContext
);
2346 TextureStateTrackingContext
* context
= context_owned
.get();
2348 FakeOutputSurfaceClient output_surface_client
;
2349 scoped_ptr
<OutputSurface
> output_surface(FakeOutputSurface::Create3d(
2350 context_owned
.PassAs
<TestWebGraphicsContext3D
>()));
2351 CHECK(output_surface
->BindToClient(&output_surface_client
));
2353 scoped_ptr
<ResourceProvider
> resource_provider(ResourceProvider::Create(
2354 output_surface
.get(), shared_bitmap_manager_
.get(), 0, false, 1, false));
2356 gfx::Size
size(1, 1);
2357 ResourceFormat format
= RGBA_8888
;
2358 GLenum texture_pool
= GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
;
2360 for (int texture_id
= 1; texture_id
<= 2; ++texture_id
) {
2361 GLint wrap_mode
= texture_id
== 1 ? GL_CLAMP_TO_EDGE
: GL_REPEAT
;
2362 // Check that the texture gets created with the right sampler settings.
2363 ResourceProvider::ResourceId id
=
2364 resource_provider
->CreateGLTexture(size
,
2368 ResourceProvider::TextureUsageAny
,
2370 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
));
2371 EXPECT_CALL(*context
,
2372 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
));
2373 EXPECT_CALL(*context
,
2374 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
));
2377 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, wrap_mode
));
2380 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, wrap_mode
));
2381 EXPECT_CALL(*context
,
2382 texParameteri(GL_TEXTURE_2D
,
2383 GL_TEXTURE_POOL_CHROMIUM
,
2384 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
));
2385 resource_provider
->CreateForTesting(id
);
2388 Mock::VerifyAndClearExpectations(context
);
2392 TEST_P(ResourceProviderTest
, TextureMailbox_SharedMemory
) {
2393 if (GetParam() != ResourceProvider::Bitmap
)
2396 gfx::Size
size(64, 64);
2397 const uint32_t kBadBeef
= 0xbadbeef;
2398 scoped_ptr
<base::SharedMemory
> shared_memory(
2399 CreateAndFillSharedMemory(size
, kBadBeef
));
2401 FakeOutputSurfaceClient output_surface_client
;
2402 scoped_ptr
<OutputSurface
> output_surface(
2403 FakeOutputSurface::CreateSoftware(make_scoped_ptr(
2404 new SoftwareOutputDevice
)));
2405 CHECK(output_surface
->BindToClient(&output_surface_client
));
2407 scoped_ptr
<ResourceProvider
> resource_provider(ResourceProvider::Create(
2408 output_surface
.get(), shared_bitmap_manager_
.get(), 0, false, 1, false));
2410 scoped_ptr
<SingleReleaseCallback
> callback
= SingleReleaseCallback::Create(
2411 base::Bind(&EmptyReleaseCallback
));
2412 TextureMailbox
mailbox(shared_memory
.get(), size
);
2414 ResourceProvider::ResourceId id
=
2415 resource_provider
->CreateResourceFromTextureMailbox(
2416 mailbox
, callback
.Pass());
2420 ResourceProvider::ScopedReadLockSoftware
lock(resource_provider
.get(), id
);
2421 const SkBitmap
* sk_bitmap
= lock
.sk_bitmap();
2422 EXPECT_EQ(sk_bitmap
->width(), size
.width());
2423 EXPECT_EQ(sk_bitmap
->height(), size
.height());
2424 EXPECT_EQ(*sk_bitmap
->getAddr32(16, 16), kBadBeef
);
2428 TEST_P(ResourceProviderTest
, TextureMailbox_GLTexture2D
) {
2429 // Mailboxing is only supported for GL textures.
2430 if (GetParam() != ResourceProvider::GLTexture
)
2433 scoped_ptr
<TextureStateTrackingContext
> context_owned(
2434 new TextureStateTrackingContext
);
2435 TextureStateTrackingContext
* context
= context_owned
.get();
2437 FakeOutputSurfaceClient output_surface_client
;
2438 scoped_ptr
<OutputSurface
> output_surface(FakeOutputSurface::Create3d(
2439 context_owned
.PassAs
<TestWebGraphicsContext3D
>()));
2440 CHECK(output_surface
->BindToClient(&output_surface_client
));
2442 scoped_ptr
<ResourceProvider
> resource_provider(ResourceProvider::Create(
2443 output_surface
.get(), shared_bitmap_manager_
.get(), 0, false, 1, false));
2445 unsigned texture_id
= 1;
2446 uint32 sync_point
= 30;
2447 unsigned target
= GL_TEXTURE_2D
;
2449 EXPECT_CALL(*context
, bindTexture(_
, _
)).Times(0);
2450 EXPECT_CALL(*context
, waitSyncPoint(_
)).Times(0);
2451 EXPECT_CALL(*context
, insertSyncPoint()).Times(0);
2452 EXPECT_CALL(*context
, produceTextureCHROMIUM(_
, _
)).Times(0);
2453 EXPECT_CALL(*context
, consumeTextureCHROMIUM(_
, _
)).Times(0);
2455 gpu::Mailbox gpu_mailbox
;
2456 memcpy(gpu_mailbox
.name
, "Hello world", strlen("Hello world") + 1);
2457 scoped_ptr
<SingleReleaseCallback
> callback
= SingleReleaseCallback::Create(
2458 base::Bind(&EmptyReleaseCallback
));
2460 TextureMailbox
mailbox(gpu_mailbox
, target
, sync_point
);
2462 ResourceProvider::ResourceId id
=
2463 resource_provider
->CreateResourceFromTextureMailbox(
2464 mailbox
, callback
.Pass());
2467 Mock::VerifyAndClearExpectations(context
);
2470 // Using the texture does a consume of the mailbox.
2471 EXPECT_CALL(*context
, bindTexture(target
, texture_id
));
2472 EXPECT_CALL(*context
, waitSyncPoint(sync_point
));
2473 EXPECT_CALL(*context
, consumeTextureCHROMIUM(target
, _
));
2475 EXPECT_CALL(*context
, insertSyncPoint()).Times(0);
2476 EXPECT_CALL(*context
, produceTextureCHROMIUM(_
, _
)).Times(0);
2478 ResourceProvider::ScopedReadLockGL
lock(resource_provider
.get(), id
);
2479 Mock::VerifyAndClearExpectations(context
);
2481 // When done with it, a sync point should be inserted, but no produce is
2483 EXPECT_CALL(*context
, bindTexture(_
, _
)).Times(0);
2484 EXPECT_CALL(*context
, insertSyncPoint());
2485 EXPECT_CALL(*context
, produceTextureCHROMIUM(_
, _
)).Times(0);
2487 EXPECT_CALL(*context
, waitSyncPoint(_
)).Times(0);
2488 EXPECT_CALL(*context
, consumeTextureCHROMIUM(_
, _
)).Times(0);
2492 TEST_P(ResourceProviderTest
, TextureMailbox_GLTextureExternalOES
) {
2493 // Mailboxing is only supported for GL textures.
2494 if (GetParam() != ResourceProvider::GLTexture
)
2497 scoped_ptr
<TextureStateTrackingContext
> context_owned(
2498 new TextureStateTrackingContext
);
2499 TextureStateTrackingContext
* context
= context_owned
.get();
2501 FakeOutputSurfaceClient output_surface_client
;
2502 scoped_ptr
<OutputSurface
> output_surface(FakeOutputSurface::Create3d(
2503 context_owned
.PassAs
<TestWebGraphicsContext3D
>()));
2504 CHECK(output_surface
->BindToClient(&output_surface_client
));
2506 scoped_ptr
<ResourceProvider
> resource_provider(ResourceProvider::Create(
2507 output_surface
.get(), shared_bitmap_manager_
.get(), 0, false, 1, false));
2509 unsigned texture_id
= 1;
2510 uint32 sync_point
= 30;
2511 unsigned target
= GL_TEXTURE_EXTERNAL_OES
;
2513 EXPECT_CALL(*context
, bindTexture(_
, _
)).Times(0);
2514 EXPECT_CALL(*context
, waitSyncPoint(_
)).Times(0);
2515 EXPECT_CALL(*context
, insertSyncPoint()).Times(0);
2516 EXPECT_CALL(*context
, produceTextureCHROMIUM(_
, _
)).Times(0);
2517 EXPECT_CALL(*context
, consumeTextureCHROMIUM(_
, _
)).Times(0);
2519 gpu::Mailbox gpu_mailbox
;
2520 memcpy(gpu_mailbox
.name
, "Hello world", strlen("Hello world") + 1);
2521 scoped_ptr
<SingleReleaseCallback
> callback
= SingleReleaseCallback::Create(
2522 base::Bind(&EmptyReleaseCallback
));
2524 TextureMailbox
mailbox(gpu_mailbox
, target
, sync_point
);
2526 ResourceProvider::ResourceId id
=
2527 resource_provider
->CreateResourceFromTextureMailbox(
2528 mailbox
, callback
.Pass());
2531 Mock::VerifyAndClearExpectations(context
);
2534 // Using the texture does a consume of the mailbox.
2535 EXPECT_CALL(*context
, bindTexture(target
, texture_id
));
2536 EXPECT_CALL(*context
, waitSyncPoint(sync_point
));
2537 EXPECT_CALL(*context
, consumeTextureCHROMIUM(target
, _
));
2539 EXPECT_CALL(*context
, insertSyncPoint()).Times(0);
2540 EXPECT_CALL(*context
, produceTextureCHROMIUM(_
, _
)).Times(0);
2542 ResourceProvider::ScopedReadLockGL
lock(resource_provider
.get(), id
);
2543 Mock::VerifyAndClearExpectations(context
);
2545 // When done with it, a sync point should be inserted, but no produce is
2547 EXPECT_CALL(*context
, bindTexture(_
, _
)).Times(0);
2548 EXPECT_CALL(*context
, insertSyncPoint());
2549 EXPECT_CALL(*context
, produceTextureCHROMIUM(_
, _
)).Times(0);
2551 EXPECT_CALL(*context
, waitSyncPoint(_
)).Times(0);
2552 EXPECT_CALL(*context
, consumeTextureCHROMIUM(_
, _
)).Times(0);
2556 class AllocationTrackingContext3D
: public TestWebGraphicsContext3D
{
2558 MOCK_METHOD0(NextTextureId
, GLuint());
2559 MOCK_METHOD1(RetireTextureId
, void(GLuint id
));
2560 MOCK_METHOD2(bindTexture
, void(GLenum target
, GLuint texture
));
2561 MOCK_METHOD5(texStorage2DEXT
,
2564 GLuint internalformat
,
2567 MOCK_METHOD9(texImage2D
,
2570 GLenum internalformat
,
2576 const void* pixels
));
2577 MOCK_METHOD9(texSubImage2D
,
2586 const void* pixels
));
2587 MOCK_METHOD9(asyncTexImage2DCHROMIUM
,
2590 GLenum internalformat
,
2596 const void* pixels
));
2597 MOCK_METHOD9(asyncTexSubImage2DCHROMIUM
,
2606 const void* pixels
));
2607 MOCK_METHOD8(compressedTexImage2D
,
2610 GLenum internalformat
,
2616 MOCK_METHOD1(waitAsyncTexImage2DCHROMIUM
, void(GLenum
));
2617 MOCK_METHOD4(createImageCHROMIUM
, GLuint(GLsizei
, GLsizei
, GLenum
, GLenum
));
2618 MOCK_METHOD1(destroyImageCHROMIUM
, void(GLuint
));
2619 MOCK_METHOD1(mapImageCHROMIUM
, void*(GLuint
));
2620 MOCK_METHOD3(getImageParameterivCHROMIUM
, void(GLuint
, GLenum
, GLint
*));
2621 MOCK_METHOD1(unmapImageCHROMIUM
, void(GLuint
));
2622 MOCK_METHOD2(bindTexImage2DCHROMIUM
, void(GLenum
, GLint
));
2623 MOCK_METHOD2(releaseTexImage2DCHROMIUM
, void(GLenum
, GLint
));
2625 // We're mocking bindTexture, so we override
2626 // TestWebGraphicsContext3D::texParameteri to avoid assertions related to the
2627 // currently bound texture.
2628 virtual void texParameteri(GLenum target
, GLenum pname
, GLint param
) {}
2631 TEST_P(ResourceProviderTest
, TextureAllocation
) {
2632 // Only for GL textures.
2633 if (GetParam() != ResourceProvider::GLTexture
)
2635 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
2636 new StrictMock
<AllocationTrackingContext3D
>);
2637 AllocationTrackingContext3D
* context
= context_owned
.get();
2639 FakeOutputSurfaceClient output_surface_client
;
2640 scoped_ptr
<OutputSurface
> output_surface(FakeOutputSurface::Create3d(
2641 context_owned
.PassAs
<TestWebGraphicsContext3D
>()));
2642 CHECK(output_surface
->BindToClient(&output_surface_client
));
2644 scoped_ptr
<ResourceProvider
> resource_provider(ResourceProvider::Create(
2645 output_surface
.get(), shared_bitmap_manager_
.get(), 0, false, 1, false));
2647 gfx::Size
size(2, 2);
2648 gfx::Vector2d
offset(0, 0);
2649 gfx::Rect
rect(0, 0, 2, 2);
2650 ResourceFormat format
= RGBA_8888
;
2651 ResourceProvider::ResourceId id
= 0;
2652 uint8_t pixels
[16] = { 0 };
2653 int texture_id
= 123;
2655 // Lazy allocation. Don't allocate when creating the resource.
2656 id
= resource_provider
->CreateResource(
2657 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureUsageAny
, format
);
2659 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
2660 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(1);
2661 resource_provider
->CreateForTesting(id
);
2663 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
2664 resource_provider
->DeleteResource(id
);
2666 Mock::VerifyAndClearExpectations(context
);
2668 // Do allocate when we set the pixels.
2669 id
= resource_provider
->CreateResource(
2670 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureUsageAny
, format
);
2672 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
2673 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(3);
2674 EXPECT_CALL(*context
, texImage2D(_
, _
, _
, 2, 2, _
, _
, _
, _
)).Times(1);
2675 EXPECT_CALL(*context
, texSubImage2D(_
, _
, _
, _
, 2, 2, _
, _
, _
)).Times(1);
2676 resource_provider
->SetPixels(id
, pixels
, rect
, rect
, offset
);
2678 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
2679 resource_provider
->DeleteResource(id
);
2681 Mock::VerifyAndClearExpectations(context
);
2683 // Same for async version.
2684 id
= resource_provider
->CreateResource(
2685 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureUsageAny
, format
);
2686 resource_provider
->AcquirePixelRasterBuffer(id
);
2688 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
2689 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(2);
2690 EXPECT_CALL(*context
, asyncTexImage2DCHROMIUM(_
, _
, _
, 2, 2, _
, _
, _
, _
))
2692 resource_provider
->BeginSetPixels(id
);
2693 ASSERT_TRUE(resource_provider
->DidSetPixelsComplete(id
));
2695 resource_provider
->ReleasePixelRasterBuffer(id
);
2697 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
2698 resource_provider
->DeleteResource(id
);
2700 Mock::VerifyAndClearExpectations(context
);
2703 TEST_P(ResourceProviderTest
, TextureAllocationStorageUsageAny
) {
2704 // Only for GL textures.
2705 if (GetParam() != ResourceProvider::GLTexture
)
2707 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
2708 new StrictMock
<AllocationTrackingContext3D
>);
2709 AllocationTrackingContext3D
* context
= context_owned
.get();
2710 context
->set_support_texture_storage(true);
2712 FakeOutputSurfaceClient output_surface_client
;
2713 scoped_ptr
<OutputSurface
> output_surface(FakeOutputSurface::Create3d(
2714 context_owned
.PassAs
<TestWebGraphicsContext3D
>()));
2715 CHECK(output_surface
->BindToClient(&output_surface_client
));
2717 scoped_ptr
<ResourceProvider
> resource_provider(ResourceProvider::Create(
2718 output_surface
.get(), shared_bitmap_manager_
.get(), 0, false, 1, false));
2720 gfx::Size
size(2, 2);
2721 ResourceFormat format
= RGBA_8888
;
2722 ResourceProvider::ResourceId id
= 0;
2723 int texture_id
= 123;
2725 // Lazy allocation. Don't allocate when creating the resource.
2726 id
= resource_provider
->CreateResource(
2727 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureUsageAny
, format
);
2729 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
2730 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(2);
2731 EXPECT_CALL(*context
, texStorage2DEXT(_
, _
, _
, 2, 2)).Times(1);
2732 resource_provider
->AllocateForTesting(id
);
2734 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
2735 resource_provider
->DeleteResource(id
);
2737 Mock::VerifyAndClearExpectations(context
);
2740 TEST_P(ResourceProviderTest
, TextureAllocationStorageUsageFramebuffer
) {
2741 // Only for GL textures.
2742 if (GetParam() != ResourceProvider::GLTexture
)
2744 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
2745 new StrictMock
<AllocationTrackingContext3D
>);
2746 AllocationTrackingContext3D
* context
= context_owned
.get();
2747 context
->set_support_texture_storage(true);
2749 FakeOutputSurfaceClient output_surface_client
;
2750 scoped_ptr
<OutputSurface
> output_surface(FakeOutputSurface::Create3d(
2751 context_owned
.PassAs
<TestWebGraphicsContext3D
>()));
2752 CHECK(output_surface
->BindToClient(&output_surface_client
));
2754 scoped_ptr
<ResourceProvider
> resource_provider(ResourceProvider::Create(
2755 output_surface
.get(), shared_bitmap_manager_
.get(), 0, false, 1, false));
2757 gfx::Size
size(2, 2);
2758 ResourceFormat format
= RGBA_8888
;
2759 ResourceProvider::ResourceId id
= 0;
2760 int texture_id
= 123;
2762 // Lazy allocation. Don't allocate when creating the resource.
2763 id
= resource_provider
->CreateResource(
2766 ResourceProvider::TextureUsageFramebuffer
,
2769 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
2770 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(2);
2771 EXPECT_CALL(*context
, texImage2D(_
, _
, _
, 2, 2, _
, _
, _
, _
)).Times(1);
2772 resource_provider
->AllocateForTesting(id
);
2774 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
2775 resource_provider
->DeleteResource(id
);
2777 Mock::VerifyAndClearExpectations(context
);
2780 TEST_P(ResourceProviderTest
, PixelBuffer_GLTexture
) {
2781 if (GetParam() != ResourceProvider::GLTexture
)
2783 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
2784 new StrictMock
<AllocationTrackingContext3D
>);
2785 AllocationTrackingContext3D
* context
= context_owned
.get();
2787 FakeOutputSurfaceClient output_surface_client
;
2788 scoped_ptr
<OutputSurface
> output_surface(FakeOutputSurface::Create3d(
2789 context_owned
.PassAs
<TestWebGraphicsContext3D
>()));
2790 CHECK(output_surface
->BindToClient(&output_surface_client
));
2792 gfx::Size
size(2, 2);
2793 ResourceFormat format
= RGBA_8888
;
2794 ResourceProvider::ResourceId id
= 0;
2795 int texture_id
= 123;
2797 scoped_ptr
<ResourceProvider
> resource_provider(ResourceProvider::Create(
2798 output_surface
.get(), shared_bitmap_manager_
.get(), 0, false, 1, false));
2800 id
= resource_provider
->CreateResource(
2801 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureUsageAny
, format
);
2802 resource_provider
->AcquirePixelRasterBuffer(id
);
2804 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
2805 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(2);
2806 EXPECT_CALL(*context
, asyncTexImage2DCHROMIUM(_
, _
, _
, 2, 2, _
, _
, _
, _
))
2808 resource_provider
->BeginSetPixels(id
);
2810 EXPECT_TRUE(resource_provider
->DidSetPixelsComplete(id
));
2812 resource_provider
->ReleasePixelRasterBuffer(id
);
2814 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
2815 resource_provider
->DeleteResource(id
);
2817 Mock::VerifyAndClearExpectations(context
);
2820 TEST_P(ResourceProviderTest
, ForcingAsyncUploadToComplete
) {
2821 // Only for GL textures.
2822 if (GetParam() != ResourceProvider::GLTexture
)
2824 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
2825 new StrictMock
<AllocationTrackingContext3D
>);
2826 AllocationTrackingContext3D
* context
= context_owned
.get();
2828 FakeOutputSurfaceClient output_surface_client
;
2829 scoped_ptr
<OutputSurface
> output_surface(FakeOutputSurface::Create3d(
2830 context_owned
.PassAs
<TestWebGraphicsContext3D
>()));
2831 CHECK(output_surface
->BindToClient(&output_surface_client
));
2833 gfx::Size
size(2, 2);
2834 ResourceFormat format
= RGBA_8888
;
2835 ResourceProvider::ResourceId id
= 0;
2836 int texture_id
= 123;
2838 scoped_ptr
<ResourceProvider
> resource_provider(ResourceProvider::Create(
2839 output_surface
.get(), shared_bitmap_manager_
.get(), 0, false, 1, false));
2841 id
= resource_provider
->CreateResource(
2842 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureUsageAny
, format
);
2843 resource_provider
->AcquirePixelRasterBuffer(id
);
2845 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
2846 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(2);
2847 EXPECT_CALL(*context
, asyncTexImage2DCHROMIUM(_
, _
, _
, 2, 2, _
, _
, _
, _
))
2849 resource_provider
->BeginSetPixels(id
);
2851 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(1);
2852 EXPECT_CALL(*context
, waitAsyncTexImage2DCHROMIUM(GL_TEXTURE_2D
)).Times(1);
2853 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, 0)).Times(1);
2854 resource_provider
->ForceSetPixelsToComplete(id
);
2856 resource_provider
->ReleasePixelRasterBuffer(id
);
2858 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
2859 resource_provider
->DeleteResource(id
);
2861 Mock::VerifyAndClearExpectations(context
);
2864 TEST_P(ResourceProviderTest
, PixelBufferLostContext
) {
2865 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
2866 new NiceMock
<AllocationTrackingContext3D
>);
2867 AllocationTrackingContext3D
* context
= context_owned
.get();
2869 FakeOutputSurfaceClient output_surface_client
;
2870 scoped_ptr
<OutputSurface
> output_surface(FakeOutputSurface::Create3d(
2871 context_owned
.PassAs
<TestWebGraphicsContext3D
>()));
2872 CHECK(output_surface
->BindToClient(&output_surface_client
));
2874 gfx::Size
size(2, 2);
2875 ResourceFormat format
= RGBA_8888
;
2876 ResourceProvider::ResourceId id
= 0;
2877 int texture_id
= 123;
2879 scoped_ptr
<ResourceProvider
> resource_provider(ResourceProvider::Create(
2880 output_surface
.get(), shared_bitmap_manager_
.get(), 0, false, 1, false));
2882 EXPECT_CALL(*context
, NextTextureId()).WillRepeatedly(Return(texture_id
));
2884 id
= resource_provider
->CreateResource(
2885 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureUsageAny
, format
);
2886 context
->loseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB
,
2887 GL_INNOCENT_CONTEXT_RESET_ARB
);
2889 resource_provider
->AcquirePixelRasterBuffer(id
);
2890 SkCanvas
* raster_canvas
= resource_provider
->MapPixelRasterBuffer(id
);
2891 EXPECT_TRUE(raster_canvas
== NULL
);
2892 resource_provider
->UnmapPixelRasterBuffer(id
);
2893 resource_provider
->ReleasePixelRasterBuffer(id
);
2894 Mock::VerifyAndClearExpectations(context
);
2897 TEST_P(ResourceProviderTest
, Image_GLTexture
) {
2898 // Only for GL textures.
2899 if (GetParam() != ResourceProvider::GLTexture
)
2901 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
2902 new StrictMock
<AllocationTrackingContext3D
>);
2903 AllocationTrackingContext3D
* context
= context_owned
.get();
2905 FakeOutputSurfaceClient output_surface_client
;
2906 scoped_ptr
<OutputSurface
> output_surface(FakeOutputSurface::Create3d(
2907 context_owned
.PassAs
<TestWebGraphicsContext3D
>()));
2908 CHECK(output_surface
->BindToClient(&output_surface_client
));
2910 const int kWidth
= 2;
2911 const int kHeight
= 2;
2912 gfx::Size
size(kWidth
, kHeight
);
2913 ResourceFormat format
= RGBA_8888
;
2914 ResourceProvider::ResourceId id
= 0;
2915 const unsigned kTextureId
= 123u;
2916 const unsigned kImageId
= 234u;
2918 scoped_ptr
<ResourceProvider
> resource_provider(ResourceProvider::Create(
2919 output_surface
.get(), shared_bitmap_manager_
.get(), 0, false, 1, false));
2921 id
= resource_provider
->CreateResource(
2922 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureUsageAny
, format
);
2924 const int kStride
= 4;
2925 void* dummy_mapped_buffer_address
= NULL
;
2928 createImageCHROMIUM(kWidth
, kHeight
, GL_RGBA8_OES
, GL_IMAGE_MAP_CHROMIUM
))
2929 .WillOnce(Return(kImageId
))
2930 .RetiresOnSaturation();
2931 EXPECT_CALL(*context
, getImageParameterivCHROMIUM(kImageId
,
2932 GL_IMAGE_ROWBYTES_CHROMIUM
,
2934 .WillOnce(SetArgPointee
<2>(kStride
))
2935 .RetiresOnSaturation();
2936 EXPECT_CALL(*context
, mapImageCHROMIUM(kImageId
))
2937 .WillOnce(Return(dummy_mapped_buffer_address
))
2938 .RetiresOnSaturation();
2939 resource_provider
->MapImageRasterBuffer(id
);
2941 EXPECT_CALL(*context
, unmapImageCHROMIUM(kImageId
))
2943 .RetiresOnSaturation();
2944 resource_provider
->UnmapImageRasterBuffer(id
);
2946 EXPECT_CALL(*context
, NextTextureId())
2947 .WillOnce(Return(kTextureId
))
2948 .RetiresOnSaturation();
2949 // Once in CreateTextureId and once in BindForSampling
2950 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, kTextureId
)).Times(2)
2951 .RetiresOnSaturation();
2952 EXPECT_CALL(*context
, bindTexImage2DCHROMIUM(GL_TEXTURE_2D
, kImageId
))
2954 .RetiresOnSaturation();
2956 ResourceProvider::ScopedSamplerGL
lock_gl(
2957 resource_provider
.get(), id
, GL_TEXTURE_2D
, GL_LINEAR
);
2958 EXPECT_EQ(kTextureId
, lock_gl
.texture_id());
2963 getImageParameterivCHROMIUM(kImageId
, GL_IMAGE_ROWBYTES_CHROMIUM
, _
))
2964 .WillOnce(SetArgPointee
<2>(kStride
))
2965 .RetiresOnSaturation();
2966 EXPECT_CALL(*context
, mapImageCHROMIUM(kImageId
))
2967 .WillOnce(Return(dummy_mapped_buffer_address
))
2968 .RetiresOnSaturation();
2969 resource_provider
->MapImageRasterBuffer(id
);
2971 EXPECT_CALL(*context
, unmapImageCHROMIUM(kImageId
))
2973 .RetiresOnSaturation();
2974 resource_provider
->UnmapImageRasterBuffer(id
);
2976 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, kTextureId
)).Times(1)
2977 .RetiresOnSaturation();
2978 EXPECT_CALL(*context
, releaseTexImage2DCHROMIUM(GL_TEXTURE_2D
, kImageId
))
2980 .RetiresOnSaturation();
2981 EXPECT_CALL(*context
, bindTexImage2DCHROMIUM(GL_TEXTURE_2D
, kImageId
))
2983 .RetiresOnSaturation();
2984 EXPECT_CALL(*context
, RetireTextureId(kTextureId
))
2986 .RetiresOnSaturation();
2988 ResourceProvider::ScopedSamplerGL
lock_gl(
2989 resource_provider
.get(), id
, GL_TEXTURE_2D
, GL_LINEAR
);
2990 EXPECT_EQ(kTextureId
, lock_gl
.texture_id());
2993 EXPECT_CALL(*context
, destroyImageCHROMIUM(kImageId
))
2995 .RetiresOnSaturation();
2998 TEST_P(ResourceProviderTest
, Image_Bitmap
) {
2999 if (GetParam() != ResourceProvider::Bitmap
)
3001 FakeOutputSurfaceClient output_surface_client
;
3002 scoped_ptr
<OutputSurface
> output_surface(
3003 FakeOutputSurface::CreateSoftware(make_scoped_ptr(
3004 new SoftwareOutputDevice
)));
3005 CHECK(output_surface
->BindToClient(&output_surface_client
));
3007 gfx::Size
size(1, 1);
3008 ResourceFormat format
= RGBA_8888
;
3009 ResourceProvider::ResourceId id
= 0;
3010 const uint32_t kBadBeef
= 0xbadbeef;
3012 scoped_ptr
<ResourceProvider
> resource_provider(ResourceProvider::Create(
3013 output_surface
.get(), shared_bitmap_manager_
.get(), 0, false, 1, false));
3015 id
= resource_provider
->CreateResource(
3016 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureUsageAny
, format
);
3019 bitmap
.allocN32Pixels(size
.width(), size
.height());
3020 *(bitmap
.getAddr32(0, 0)) = kBadBeef
;
3021 SkCanvas
* canvas
= resource_provider
->MapImageRasterBuffer(id
);
3022 ASSERT_TRUE(!!canvas
);
3023 canvas
->writePixels(bitmap
, 0, 0);
3024 resource_provider
->UnmapImageRasterBuffer(id
);
3027 ResourceProvider::ScopedReadLockSoftware
lock(resource_provider
.get(), id
);
3028 const SkBitmap
* sk_bitmap
= lock
.sk_bitmap();
3029 EXPECT_EQ(sk_bitmap
->width(), size
.width());
3030 EXPECT_EQ(sk_bitmap
->height(), size
.height());
3031 EXPECT_EQ(*sk_bitmap
->getAddr32(0, 0), kBadBeef
);
3034 resource_provider
->DeleteResource(id
);
3037 TEST_P(ResourceProviderTest
, CopyResource_GLTexture
) {
3038 if (GetParam() != ResourceProvider::GLTexture
)
3040 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3041 new StrictMock
<AllocationTrackingContext3D
>);
3042 AllocationTrackingContext3D
* context
= context_owned
.get();
3043 context_owned
->set_support_sync_query(true);
3045 FakeOutputSurfaceClient output_surface_client
;
3046 scoped_ptr
<OutputSurface
> output_surface(FakeOutputSurface::Create3d(
3047 context_owned
.PassAs
<TestWebGraphicsContext3D
>()));
3048 ASSERT_TRUE(output_surface
->BindToClient(&output_surface_client
));
3050 const int kWidth
= 2;
3051 const int kHeight
= 2;
3052 gfx::Size
size(kWidth
, kHeight
);
3053 ResourceFormat format
= RGBA_8888
;
3054 ResourceProvider::ResourceId source_id
= 0;
3055 ResourceProvider::ResourceId dest_id
= 0;
3056 const unsigned kSourceTextureId
= 123u;
3057 const unsigned kDestTextureId
= 321u;
3058 const unsigned kImageId
= 234u;
3060 scoped_ptr
<ResourceProvider
> resource_provider(ResourceProvider::Create(
3061 output_surface
.get(), shared_bitmap_manager_
.get(), 0, false, 1, false));
3063 source_id
= resource_provider
->CreateResource(
3064 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureUsageAny
, format
);
3066 const int kStride
= 4;
3067 void* dummy_mapped_buffer_address
= NULL
;
3070 createImageCHROMIUM(kWidth
, kHeight
, GL_RGBA8_OES
, GL_IMAGE_MAP_CHROMIUM
))
3071 .WillOnce(Return(kImageId
))
3072 .RetiresOnSaturation();
3075 getImageParameterivCHROMIUM(kImageId
, GL_IMAGE_ROWBYTES_CHROMIUM
, _
))
3076 .WillOnce(SetArgPointee
<2>(kStride
))
3077 .RetiresOnSaturation();
3078 EXPECT_CALL(*context
, mapImageCHROMIUM(kImageId
))
3079 .WillOnce(Return(dummy_mapped_buffer_address
))
3080 .RetiresOnSaturation();
3081 resource_provider
->MapImageRasterBuffer(source_id
);
3082 Mock::VerifyAndClearExpectations(context
);
3084 EXPECT_CALL(*context
, unmapImageCHROMIUM(kImageId
))
3086 .RetiresOnSaturation();
3087 resource_provider
->UnmapImageRasterBuffer(source_id
);
3088 Mock::VerifyAndClearExpectations(context
);
3090 dest_id
= resource_provider
->CreateResource(
3091 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureUsageAny
, format
);
3093 EXPECT_CALL(*context
, NextTextureId())
3094 .WillOnce(Return(kDestTextureId
))
3095 .RetiresOnSaturation();
3096 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, kDestTextureId
))
3098 .RetiresOnSaturation();
3099 EXPECT_CALL(*context
, NextTextureId())
3100 .WillOnce(Return(kSourceTextureId
))
3101 .RetiresOnSaturation();
3102 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, kSourceTextureId
))
3104 .RetiresOnSaturation();
3105 EXPECT_CALL(*context
, bindTexImage2DCHROMIUM(GL_TEXTURE_2D
, kImageId
))
3107 .RetiresOnSaturation();
3108 resource_provider
->CopyResource(source_id
, dest_id
);
3109 Mock::VerifyAndClearExpectations(context
);
3111 EXPECT_CALL(*context
, destroyImageCHROMIUM(kImageId
))
3113 .RetiresOnSaturation();
3114 EXPECT_CALL(*context
, RetireTextureId(kSourceTextureId
))
3116 .RetiresOnSaturation();
3117 EXPECT_CALL(*context
, RetireTextureId(kDestTextureId
))
3119 .RetiresOnSaturation();
3120 resource_provider
->DeleteResource(source_id
);
3121 resource_provider
->DeleteResource(dest_id
);
3124 TEST_P(ResourceProviderTest
, CopyResource_Bitmap
) {
3125 if (GetParam() != ResourceProvider::Bitmap
)
3127 FakeOutputSurfaceClient output_surface_client
;
3128 scoped_ptr
<OutputSurface
> output_surface(FakeOutputSurface::CreateSoftware(
3129 make_scoped_ptr(new SoftwareOutputDevice
)));
3130 CHECK(output_surface
->BindToClient(&output_surface_client
));
3132 gfx::Size
size(1, 1);
3133 ResourceFormat format
= RGBA_8888
;
3134 ResourceProvider::ResourceId source_id
= 0;
3135 ResourceProvider::ResourceId dest_id
= 0;
3136 const uint32_t kBadBeef
= 0xbadbeef;
3138 scoped_ptr
<ResourceProvider
> resource_provider(ResourceProvider::Create(
3139 output_surface
.get(), shared_bitmap_manager_
.get(), 0, false, 1, false));
3141 source_id
= resource_provider
->CreateResource(
3142 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureUsageAny
, format
);
3145 bitmap
.allocN32Pixels(size
.width(), size
.height());
3146 *(bitmap
.getAddr32(0, 0)) = kBadBeef
;
3147 SkCanvas
* canvas
= resource_provider
->MapImageRasterBuffer(source_id
);
3148 ASSERT_TRUE(!!canvas
);
3149 canvas
->writePixels(bitmap
, 0, 0);
3150 resource_provider
->UnmapImageRasterBuffer(source_id
);
3152 dest_id
= resource_provider
->CreateResource(
3153 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureUsageAny
, format
);
3155 resource_provider
->CopyResource(source_id
, dest_id
);
3158 ResourceProvider::ScopedReadLockSoftware
lock(resource_provider
.get(),
3160 const SkBitmap
* sk_bitmap
= lock
.sk_bitmap();
3161 EXPECT_EQ(sk_bitmap
->width(), size
.width());
3162 EXPECT_EQ(sk_bitmap
->height(), size
.height());
3163 EXPECT_EQ(*sk_bitmap
->getAddr32(0, 0), kBadBeef
);
3166 resource_provider
->DeleteResource(source_id
);
3167 resource_provider
->DeleteResource(dest_id
);
3170 void InitializeGLAndCheck(ContextSharedData
* shared_data
,
3171 ResourceProvider
* resource_provider
,
3172 FakeOutputSurface
* output_surface
) {
3173 scoped_ptr
<ResourceProviderContext
> context_owned
=
3174 ResourceProviderContext::Create(shared_data
);
3175 ResourceProviderContext
* context
= context_owned
.get();
3177 scoped_refptr
<TestContextProvider
> context_provider
=
3178 TestContextProvider::Create(
3179 context_owned
.PassAs
<TestWebGraphicsContext3D
>());
3180 output_surface
->InitializeAndSetContext3d(context_provider
);
3181 resource_provider
->InitializeGL();
3183 CheckCreateResource(ResourceProvider::GLTexture
, resource_provider
, context
);
3186 TEST(ResourceProviderTest
, BasicInitializeGLSoftware
) {
3187 scoped_ptr
<ContextSharedData
> shared_data
= ContextSharedData::Create();
3188 bool delegated_rendering
= false;
3189 scoped_ptr
<FakeOutputSurface
> output_surface(
3190 FakeOutputSurface::CreateDeferredGL(
3191 scoped_ptr
<SoftwareOutputDevice
>(new SoftwareOutputDevice
),
3192 delegated_rendering
));
3193 FakeOutputSurfaceClient
client(output_surface
.get());
3194 EXPECT_TRUE(output_surface
->BindToClient(&client
));
3195 scoped_ptr
<SharedBitmapManager
> shared_bitmap_manager(
3196 new TestSharedBitmapManager());
3197 scoped_ptr
<ResourceProvider
> resource_provider(ResourceProvider::Create(
3198 output_surface
.get(), shared_bitmap_manager
.get(), 0, false, 1, false));
3200 CheckCreateResource(ResourceProvider::Bitmap
, resource_provider
.get(), NULL
);
3202 InitializeGLAndCheck(shared_data
.get(),
3203 resource_provider
.get(),
3204 output_surface
.get());
3206 resource_provider
->InitializeSoftware();
3207 output_surface
->ReleaseGL();
3208 CheckCreateResource(ResourceProvider::Bitmap
, resource_provider
.get(), NULL
);
3210 InitializeGLAndCheck(shared_data
.get(),
3211 resource_provider
.get(),
3212 output_surface
.get());
3215 TEST_P(ResourceProviderTest
, CompressedTextureETC1Allocate
) {
3216 if (GetParam() != ResourceProvider::GLTexture
)
3219 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3220 new AllocationTrackingContext3D
);
3221 AllocationTrackingContext3D
* context
= context_owned
.get();
3222 context_owned
->set_support_compressed_texture_etc1(true);
3224 FakeOutputSurfaceClient output_surface_client
;
3225 scoped_ptr
<OutputSurface
> output_surface(FakeOutputSurface::Create3d(
3226 context_owned
.PassAs
<TestWebGraphicsContext3D
>()));
3227 CHECK(output_surface
->BindToClient(&output_surface_client
));
3229 gfx::Size
size(4, 4);
3230 scoped_ptr
<ResourceProvider
> resource_provider(
3231 ResourceProvider::Create(output_surface
.get(),
3232 shared_bitmap_manager_
.get(),
3237 int texture_id
= 123;
3239 ResourceProvider::ResourceId id
= resource_provider
->CreateResource(
3240 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureUsageAny
, ETC1
);
3242 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
3243 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(2);
3244 resource_provider
->AllocateForTesting(id
);
3246 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
3247 resource_provider
->DeleteResource(id
);
3250 TEST_P(ResourceProviderTest
, CompressedTextureETC1SetPixels
) {
3251 if (GetParam() != ResourceProvider::GLTexture
)
3254 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3255 new AllocationTrackingContext3D
);
3256 AllocationTrackingContext3D
* context
= context_owned
.get();
3257 context_owned
->set_support_compressed_texture_etc1(true);
3259 FakeOutputSurfaceClient output_surface_client
;
3260 scoped_ptr
<OutputSurface
> output_surface(FakeOutputSurface::Create3d(
3261 context_owned
.PassAs
<TestWebGraphicsContext3D
>()));
3262 CHECK(output_surface
->BindToClient(&output_surface_client
));
3264 gfx::Size
size(4, 4);
3265 scoped_ptr
<ResourceProvider
> resource_provider(
3266 ResourceProvider::Create(output_surface
.get(),
3267 shared_bitmap_manager_
.get(),
3272 int texture_id
= 123;
3275 ResourceProvider::ResourceId id
= resource_provider
->CreateResource(
3276 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureUsageAny
, ETC1
);
3278 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
3279 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(3);
3280 EXPECT_CALL(*context
,
3281 compressedTexImage2D(
3282 _
, 0, _
, size
.width(), size
.height(), _
, _
, _
)).Times(1);
3283 resource_provider
->SetPixels(
3284 id
, pixels
, gfx::Rect(size
), gfx::Rect(size
), gfx::Vector2d(0, 0));
3286 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
3287 resource_provider
->DeleteResource(id
);
3290 INSTANTIATE_TEST_CASE_P(
3291 ResourceProviderTests
,
3292 ResourceProviderTest
,
3293 ::testing::Values(ResourceProvider::GLTexture
, ResourceProvider::Bitmap
));
3295 class TextureIdAllocationTrackingContext
: public TestWebGraphicsContext3D
{
3297 virtual GLuint
NextTextureId() OVERRIDE
{
3298 base::AutoLock
lock(namespace_
->lock
);
3299 return namespace_
->next_texture_id
++;
3301 virtual void RetireTextureId(GLuint
) OVERRIDE
{}
3302 GLuint
PeekTextureId() {
3303 base::AutoLock
lock(namespace_
->lock
);
3304 return namespace_
->next_texture_id
;
3308 TEST(ResourceProviderTest
, TextureAllocationChunkSize
) {
3309 scoped_ptr
<TextureIdAllocationTrackingContext
> context_owned(
3310 new TextureIdAllocationTrackingContext
);
3311 TextureIdAllocationTrackingContext
* context
= context_owned
.get();
3313 FakeOutputSurfaceClient output_surface_client
;
3314 scoped_ptr
<OutputSurface
> output_surface(FakeOutputSurface::Create3d(
3315 context_owned
.PassAs
<TestWebGraphicsContext3D
>()));
3316 CHECK(output_surface
->BindToClient(&output_surface_client
));
3317 scoped_ptr
<SharedBitmapManager
> shared_bitmap_manager(
3318 new TestSharedBitmapManager());
3320 gfx::Size
size(1, 1);
3321 ResourceFormat format
= RGBA_8888
;
3324 size_t kTextureAllocationChunkSize
= 1;
3325 scoped_ptr
<ResourceProvider
> resource_provider(
3326 ResourceProvider::Create(output_surface
.get(),
3327 shared_bitmap_manager
.get(),
3330 kTextureAllocationChunkSize
,
3333 ResourceProvider::ResourceId id
= resource_provider
->CreateResource(
3334 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureUsageAny
, format
);
3335 resource_provider
->AllocateForTesting(id
);
3336 Mock::VerifyAndClearExpectations(context
);
3338 DCHECK_EQ(2u, context
->PeekTextureId());
3339 resource_provider
->DeleteResource(id
);
3343 size_t kTextureAllocationChunkSize
= 8;
3344 scoped_ptr
<ResourceProvider
> resource_provider(
3345 ResourceProvider::Create(output_surface
.get(),
3346 shared_bitmap_manager
.get(),
3349 kTextureAllocationChunkSize
,
3352 ResourceProvider::ResourceId id
= resource_provider
->CreateResource(
3353 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureUsageAny
, format
);
3354 resource_provider
->AllocateForTesting(id
);
3355 Mock::VerifyAndClearExpectations(context
);
3357 DCHECK_EQ(10u, context
->PeekTextureId());
3358 resource_provider
->DeleteResource(id
);