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);
407 child_resource_provider_
= ResourceProvider::Create(
408 child_output_surface_
.get(),
409 shared_bitmap_manager_
.get(),
415 static void CollectResources(ReturnedResourceArray
* array
,
416 const ReturnedResourceArray
& returned
) {
417 array
->insert(array
->end(), returned
.begin(), returned
.end());
420 static ReturnCallback
GetReturnCallback(ReturnedResourceArray
* array
) {
421 return base::Bind(&ResourceProviderTest::CollectResources
, array
);
424 static void SetResourceFilter(ResourceProvider
* resource_provider
,
425 ResourceProvider::ResourceId id
,
427 ResourceProvider::ScopedSamplerGL
sampler(
428 resource_provider
, id
, GL_TEXTURE_2D
, filter
);
431 ResourceProviderContext
* context() { return context3d_
; }
433 ResourceProvider::ResourceId
CreateChildMailbox(uint32
* release_sync_point
,
435 bool* release_called
,
436 uint32
* sync_point
) {
437 if (GetParam() == ResourceProvider::GLTexture
) {
438 unsigned texture
= child_context_
->createTexture();
439 gpu::Mailbox gpu_mailbox
;
440 child_context_
->bindTexture(GL_TEXTURE_2D
, texture
);
441 child_context_
->genMailboxCHROMIUM(gpu_mailbox
.name
);
442 child_context_
->produceTextureCHROMIUM(GL_TEXTURE_2D
, gpu_mailbox
.name
);
443 *sync_point
= child_context_
->insertSyncPoint();
444 EXPECT_LT(0u, *sync_point
);
446 scoped_ptr
<base::SharedMemory
> shared_memory
;
447 scoped_ptr
<SingleReleaseCallback
> callback
=
448 SingleReleaseCallback::Create(base::Bind(ReleaseSharedMemoryCallback
,
449 base::Passed(&shared_memory
),
453 return child_resource_provider_
->CreateResourceFromTextureMailbox(
454 TextureMailbox(gpu_mailbox
, GL_TEXTURE_2D
, *sync_point
),
457 gfx::Size
size(64, 64);
458 scoped_ptr
<base::SharedMemory
> shared_memory(
459 CreateAndFillSharedMemory(size
, 0));
461 base::SharedMemory
* shared_memory_ptr
= shared_memory
.get();
462 scoped_ptr
<SingleReleaseCallback
> callback
=
463 SingleReleaseCallback::Create(base::Bind(ReleaseSharedMemoryCallback
,
464 base::Passed(&shared_memory
),
468 return child_resource_provider_
->CreateResourceFromTextureMailbox(
469 TextureMailbox(shared_memory_ptr
, size
), callback
.Pass());
474 scoped_ptr
<ContextSharedData
> shared_data_
;
475 ResourceProviderContext
* context3d_
;
476 ResourceProviderContext
* child_context_
;
477 FakeOutputSurfaceClient output_surface_client_
;
478 FakeOutputSurfaceClient child_output_surface_client_
;
479 scoped_ptr
<OutputSurface
> output_surface_
;
480 scoped_ptr
<OutputSurface
> child_output_surface_
;
481 scoped_ptr
<ResourceProvider
> resource_provider_
;
482 scoped_ptr
<ResourceProvider
> child_resource_provider_
;
483 scoped_ptr
<TestSharedBitmapManager
> shared_bitmap_manager_
;
486 void CheckCreateResource(ResourceProvider::ResourceType expected_default_type
,
487 ResourceProvider
* resource_provider
,
488 ResourceProviderContext
* context
) {
489 DCHECK_EQ(expected_default_type
, resource_provider
->default_resource_type());
491 gfx::Size
size(1, 1);
492 ResourceFormat format
= RGBA_8888
;
493 size_t pixel_size
= TextureSizeBytes(size
, format
);
494 ASSERT_EQ(4U, pixel_size
);
496 ResourceProvider::ResourceId id
= resource_provider
->CreateResource(
497 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureUsageAny
, format
);
498 EXPECT_EQ(1, static_cast<int>(resource_provider
->num_resources()));
499 if (expected_default_type
== ResourceProvider::GLTexture
)
500 EXPECT_EQ(0u, context
->NumTextures());
502 uint8_t data
[4] = { 1, 2, 3, 4 };
503 gfx::Rect
rect(size
);
504 resource_provider
->SetPixels(id
, data
, rect
, rect
, gfx::Vector2d());
505 if (expected_default_type
== ResourceProvider::GLTexture
)
506 EXPECT_EQ(1u, context
->NumTextures());
508 uint8_t result
[4] = { 0 };
509 GetResourcePixels(resource_provider
, context
, id
, size
, format
, result
);
510 EXPECT_EQ(0, memcmp(data
, result
, pixel_size
));
512 resource_provider
->DeleteResource(id
);
513 EXPECT_EQ(0, static_cast<int>(resource_provider
->num_resources()));
514 if (expected_default_type
== ResourceProvider::GLTexture
)
515 EXPECT_EQ(0u, context
->NumTextures());
518 TEST_P(ResourceProviderTest
, Basic
) {
519 CheckCreateResource(GetParam(), resource_provider_
.get(), context());
522 TEST_P(ResourceProviderTest
, Upload
) {
523 gfx::Size
size(2, 2);
524 ResourceFormat format
= RGBA_8888
;
525 size_t pixel_size
= TextureSizeBytes(size
, format
);
526 ASSERT_EQ(16U, pixel_size
);
528 ResourceProvider::ResourceId id
= resource_provider_
->CreateResource(
529 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureUsageAny
, format
);
531 uint8_t image
[16] = { 0 };
532 gfx::Rect
image_rect(size
);
533 resource_provider_
->SetPixels(
534 id
, image
, image_rect
, image_rect
, gfx::Vector2d());
536 for (uint8_t i
= 0; i
< pixel_size
; ++i
)
539 uint8_t result
[16] = { 0 };
541 gfx::Rect
source_rect(0, 0, 1, 1);
542 gfx::Vector2d
dest_offset(0, 0);
543 resource_provider_
->SetPixels(
544 id
, image
, image_rect
, source_rect
, dest_offset
);
546 uint8_t expected
[16] = { 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
548 resource_provider_
.get(), context(), id
, size
, format
, result
);
549 EXPECT_EQ(0, memcmp(expected
, result
, pixel_size
));
552 gfx::Rect
source_rect(0, 0, 1, 1);
553 gfx::Vector2d
dest_offset(1, 1);
554 resource_provider_
->SetPixels(
555 id
, image
, image_rect
, source_rect
, dest_offset
);
557 uint8_t expected
[16] = { 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3 };
559 resource_provider_
.get(), context(), id
, size
, format
, result
);
560 EXPECT_EQ(0, memcmp(expected
, result
, pixel_size
));
563 gfx::Rect
source_rect(1, 0, 1, 1);
564 gfx::Vector2d
dest_offset(0, 1);
565 resource_provider_
->SetPixels(
566 id
, image
, image_rect
, source_rect
, dest_offset
);
568 uint8_t expected
[16] = { 0, 1, 2, 3, 0, 0, 0, 0, 4, 5, 6, 7, 0, 1, 2, 3 };
570 resource_provider_
.get(), context(), id
, size
, format
, result
);
571 EXPECT_EQ(0, memcmp(expected
, result
, pixel_size
));
574 gfx::Rect
offset_image_rect(gfx::Point(100, 100), size
);
575 gfx::Rect
source_rect(100, 100, 1, 1);
576 gfx::Vector2d
dest_offset(1, 0);
577 resource_provider_
->SetPixels(
578 id
, image
, offset_image_rect
, source_rect
, dest_offset
);
580 uint8_t expected
[16] = { 0, 1, 2, 3, 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3 };
582 resource_provider_
.get(), context(), id
, size
, format
, result
);
583 EXPECT_EQ(0, memcmp(expected
, result
, pixel_size
));
586 resource_provider_
->DeleteResource(id
);
589 TEST_P(ResourceProviderTest
, TransferGLResources
) {
590 if (GetParam() != ResourceProvider::GLTexture
)
592 gfx::Size
size(1, 1);
593 ResourceFormat format
= RGBA_8888
;
594 size_t pixel_size
= TextureSizeBytes(size
, format
);
595 ASSERT_EQ(4U, pixel_size
);
597 ResourceProvider::ResourceId id1
= child_resource_provider_
->CreateResource(
598 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureUsageAny
, format
);
599 uint8_t data1
[4] = { 1, 2, 3, 4 };
600 gfx::Rect
rect(size
);
601 child_resource_provider_
->SetPixels(id1
, data1
, rect
, rect
, gfx::Vector2d());
603 ResourceProvider::ResourceId id2
= child_resource_provider_
->CreateResource(
604 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureUsageAny
, format
);
605 uint8_t data2
[4] = { 5, 5, 5, 5 };
606 child_resource_provider_
->SetPixels(id2
, data2
, rect
, rect
, gfx::Vector2d());
608 ResourceProvider::ResourceId id3
= child_resource_provider_
->CreateResource(
609 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureUsageAny
, format
);
610 child_resource_provider_
->MapImageRasterBuffer(id3
);
611 child_resource_provider_
->UnmapImageRasterBuffer(id3
);
613 GLuint external_texture_id
= child_context_
->createExternalTexture();
614 child_context_
->bindTexture(GL_TEXTURE_EXTERNAL_OES
, external_texture_id
);
616 gpu::Mailbox external_mailbox
;
617 child_context_
->genMailboxCHROMIUM(external_mailbox
.name
);
618 child_context_
->produceTextureCHROMIUM(GL_TEXTURE_EXTERNAL_OES
,
619 external_mailbox
.name
);
620 const GLuint external_sync_point
= child_context_
->insertSyncPoint();
621 ResourceProvider::ResourceId id4
=
622 child_resource_provider_
->CreateResourceFromTextureMailbox(
624 external_mailbox
, GL_TEXTURE_EXTERNAL_OES
, external_sync_point
),
625 SingleReleaseCallback::Create(base::Bind(&EmptyReleaseCallback
)));
627 ReturnedResourceArray returned_to_child
;
629 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
631 // Transfer some resources to the parent.
632 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
633 resource_ids_to_transfer
.push_back(id1
);
634 resource_ids_to_transfer
.push_back(id2
);
635 resource_ids_to_transfer
.push_back(id3
);
636 resource_ids_to_transfer
.push_back(id4
);
637 TransferableResourceArray list
;
638 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
640 ASSERT_EQ(4u, list
.size());
641 EXPECT_NE(0u, list
[0].mailbox_holder
.sync_point
);
642 EXPECT_NE(0u, list
[1].mailbox_holder
.sync_point
);
643 EXPECT_EQ(list
[0].mailbox_holder
.sync_point
,
644 list
[1].mailbox_holder
.sync_point
);
645 EXPECT_NE(0u, list
[2].mailbox_holder
.sync_point
);
646 EXPECT_EQ(list
[0].mailbox_holder
.sync_point
,
647 list
[2].mailbox_holder
.sync_point
);
648 EXPECT_EQ(external_sync_point
, list
[3].mailbox_holder
.sync_point
);
649 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
650 list
[0].mailbox_holder
.texture_target
);
651 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
652 list
[1].mailbox_holder
.texture_target
);
653 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
654 list
[2].mailbox_holder
.texture_target
);
655 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_EXTERNAL_OES
),
656 list
[3].mailbox_holder
.texture_target
);
657 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
658 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
659 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id3
));
660 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id4
));
661 resource_provider_
->ReceiveFromChild(child_id
, list
);
662 EXPECT_NE(list
[0].mailbox_holder
.sync_point
,
663 context3d_
->last_waited_sync_point());
665 ResourceProvider::ScopedReadLockGL
lock(resource_provider_
.get(),
668 EXPECT_EQ(list
[0].mailbox_holder
.sync_point
,
669 context3d_
->last_waited_sync_point());
670 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
671 resource_ids_to_transfer
);
674 EXPECT_EQ(4u, resource_provider_
->num_resources());
675 ResourceProvider::ResourceIdMap resource_map
=
676 resource_provider_
->GetChildToParentMap(child_id
);
677 ResourceProvider::ResourceId mapped_id1
= resource_map
[id1
];
678 ResourceProvider::ResourceId mapped_id2
= resource_map
[id2
];
679 ResourceProvider::ResourceId mapped_id3
= resource_map
[id3
];
680 ResourceProvider::ResourceId mapped_id4
= resource_map
[id4
];
681 EXPECT_NE(0u, mapped_id1
);
682 EXPECT_NE(0u, mapped_id2
);
683 EXPECT_NE(0u, mapped_id3
);
684 EXPECT_NE(0u, mapped_id4
);
685 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id1
));
686 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id2
));
687 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id3
));
688 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id4
));
690 uint8_t result
[4] = { 0 };
692 resource_provider_
.get(), context(), mapped_id1
, size
, format
, result
);
693 EXPECT_EQ(0, memcmp(data1
, result
, pixel_size
));
696 resource_provider_
.get(), context(), mapped_id2
, size
, format
, result
);
697 EXPECT_EQ(0, memcmp(data2
, result
, pixel_size
));
700 // Check that transfering again the same resource from the child to the
702 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
703 resource_ids_to_transfer
.push_back(id1
);
704 resource_ids_to_transfer
.push_back(id2
);
705 resource_ids_to_transfer
.push_back(id3
);
706 TransferableResourceArray list
;
707 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
709 EXPECT_EQ(3u, list
.size());
710 EXPECT_EQ(id1
, list
[0].id
);
711 EXPECT_EQ(id2
, list
[1].id
);
712 EXPECT_EQ(id3
, list
[2].id
);
713 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
714 list
[0].mailbox_holder
.texture_target
);
715 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
716 list
[1].mailbox_holder
.texture_target
);
717 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
718 list
[2].mailbox_holder
.texture_target
);
719 ReturnedResourceArray returned
;
720 TransferableResource::ReturnResources(list
, &returned
);
721 child_resource_provider_
->ReceiveReturnsFromParent(returned
);
722 // ids were exported twice, we returned them only once, they should still
724 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
725 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
726 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id3
));
729 EXPECT_EQ(0u, returned_to_child
.size());
731 // Transfer resources back from the parent to the child. Set no resources as
733 ResourceProvider::ResourceIdArray no_resources
;
734 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
736 ASSERT_EQ(4u, returned_to_child
.size());
737 EXPECT_NE(0u, returned_to_child
[0].sync_point
);
738 EXPECT_NE(0u, returned_to_child
[1].sync_point
);
739 EXPECT_NE(0u, returned_to_child
[2].sync_point
);
740 EXPECT_NE(0u, returned_to_child
[3].sync_point
);
741 EXPECT_FALSE(returned_to_child
[0].lost
);
742 EXPECT_FALSE(returned_to_child
[1].lost
);
743 EXPECT_FALSE(returned_to_child
[2].lost
);
744 EXPECT_FALSE(returned_to_child
[3].lost
);
745 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
746 returned_to_child
.clear();
748 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id1
));
749 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id2
));
750 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id3
));
751 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id4
));
754 ResourceProvider::ScopedReadLockGL
lock(child_resource_provider_
.get(),
756 ASSERT_NE(0U, lock
.texture_id());
757 child_context_
->bindTexture(GL_TEXTURE_2D
, lock
.texture_id());
758 child_context_
->GetPixels(size
, format
, result
);
759 EXPECT_EQ(0, memcmp(data1
, result
, pixel_size
));
762 ResourceProvider::ScopedReadLockGL
lock(child_resource_provider_
.get(),
764 ASSERT_NE(0U, lock
.texture_id());
765 child_context_
->bindTexture(GL_TEXTURE_2D
, lock
.texture_id());
766 child_context_
->GetPixels(size
, format
, result
);
767 EXPECT_EQ(0, memcmp(data2
, result
, pixel_size
));
770 ResourceProvider::ScopedReadLockGL
lock(child_resource_provider_
.get(),
772 ASSERT_NE(0U, lock
.texture_id());
773 child_context_
->bindTexture(GL_TEXTURE_2D
, lock
.texture_id());
776 // Transfer resources to the parent again.
777 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
778 resource_ids_to_transfer
.push_back(id1
);
779 resource_ids_to_transfer
.push_back(id2
);
780 resource_ids_to_transfer
.push_back(id3
);
781 resource_ids_to_transfer
.push_back(id4
);
782 TransferableResourceArray list
;
783 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
785 ASSERT_EQ(4u, list
.size());
786 EXPECT_EQ(id1
, list
[0].id
);
787 EXPECT_EQ(id2
, list
[1].id
);
788 EXPECT_EQ(id3
, list
[2].id
);
789 EXPECT_EQ(id4
, list
[3].id
);
790 EXPECT_NE(0u, list
[0].mailbox_holder
.sync_point
);
791 EXPECT_NE(0u, list
[1].mailbox_holder
.sync_point
);
792 EXPECT_NE(0u, list
[2].mailbox_holder
.sync_point
);
793 EXPECT_NE(0u, list
[3].mailbox_holder
.sync_point
);
794 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
795 list
[0].mailbox_holder
.texture_target
);
796 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
797 list
[1].mailbox_holder
.texture_target
);
798 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
799 list
[2].mailbox_holder
.texture_target
);
800 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_EXTERNAL_OES
),
801 list
[3].mailbox_holder
.texture_target
);
802 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
803 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
804 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id3
));
805 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id4
));
806 resource_provider_
->ReceiveFromChild(child_id
, list
);
807 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
808 resource_ids_to_transfer
);
811 EXPECT_EQ(0u, returned_to_child
.size());
813 EXPECT_EQ(4u, resource_provider_
->num_resources());
814 resource_provider_
->DestroyChild(child_id
);
815 EXPECT_EQ(0u, resource_provider_
->num_resources());
817 ASSERT_EQ(4u, returned_to_child
.size());
818 EXPECT_NE(0u, returned_to_child
[0].sync_point
);
819 EXPECT_NE(0u, returned_to_child
[1].sync_point
);
820 EXPECT_NE(0u, returned_to_child
[2].sync_point
);
821 EXPECT_NE(0u, returned_to_child
[3].sync_point
);
822 EXPECT_FALSE(returned_to_child
[0].lost
);
823 EXPECT_FALSE(returned_to_child
[1].lost
);
824 EXPECT_FALSE(returned_to_child
[2].lost
);
825 EXPECT_FALSE(returned_to_child
[3].lost
);
828 TEST_P(ResourceProviderTest
, ReadLockCountStopsReturnToChildOrDelete
) {
829 if (GetParam() != ResourceProvider::GLTexture
)
831 gfx::Size
size(1, 1);
832 ResourceFormat format
= RGBA_8888
;
834 ResourceProvider::ResourceId id1
= child_resource_provider_
->CreateResource(
835 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureUsageAny
, format
);
836 uint8_t data1
[4] = {1, 2, 3, 4};
837 gfx::Rect
rect(size
);
838 child_resource_provider_
->SetPixels(id1
, data1
, rect
, rect
, gfx::Vector2d());
840 ReturnedResourceArray returned_to_child
;
842 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
844 // Transfer some resources to the parent.
845 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
846 resource_ids_to_transfer
.push_back(id1
);
847 TransferableResourceArray list
;
848 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
850 ASSERT_EQ(1u, list
.size());
851 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
853 resource_provider_
->ReceiveFromChild(child_id
, list
);
855 ResourceProvider::ScopedReadLockGL
lock(resource_provider_
.get(),
858 resource_provider_
->DeclareUsedResourcesFromChild(
859 child_id
, ResourceProvider::ResourceIdArray());
860 EXPECT_EQ(0u, returned_to_child
.size());
863 EXPECT_EQ(1u, returned_to_child
.size());
864 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
867 ResourceProvider::ScopedReadLockGL
lock(child_resource_provider_
.get(),
869 child_resource_provider_
->DeleteResource(id1
);
870 EXPECT_EQ(1u, child_resource_provider_
->num_resources());
871 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
874 EXPECT_EQ(0u, child_resource_provider_
->num_resources());
875 resource_provider_
->DestroyChild(child_id
);
878 TEST_P(ResourceProviderTest
, TransferSoftwareResources
) {
879 if (GetParam() != ResourceProvider::Bitmap
)
882 gfx::Size
size(1, 1);
883 ResourceFormat format
= RGBA_8888
;
884 size_t pixel_size
= TextureSizeBytes(size
, format
);
885 ASSERT_EQ(4U, pixel_size
);
887 ResourceProvider::ResourceId id1
= child_resource_provider_
->CreateResource(
888 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureUsageAny
, format
);
889 uint8_t data1
[4] = { 1, 2, 3, 4 };
890 gfx::Rect
rect(size
);
891 child_resource_provider_
->SetPixels(id1
, data1
, rect
, rect
, gfx::Vector2d());
893 ResourceProvider::ResourceId id2
= child_resource_provider_
->CreateResource(
894 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureUsageAny
, format
);
895 uint8_t data2
[4] = { 5, 5, 5, 5 };
896 child_resource_provider_
->SetPixels(id2
, data2
, rect
, rect
, gfx::Vector2d());
898 ResourceProvider::ResourceId id3
= child_resource_provider_
->CreateResource(
899 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureUsageAny
, format
);
900 uint8_t data3
[4] = { 6, 7, 8, 9 };
901 SkImageInfo info
= SkImageInfo::MakeN32Premul(size
.width(), size
.height());
902 SkCanvas
* raster_canvas
= child_resource_provider_
->MapImageRasterBuffer(id3
);
903 raster_canvas
->writePixels(info
, data3
, info
.minRowBytes(), 0, 0);
904 child_resource_provider_
->UnmapImageRasterBuffer(id3
);
906 scoped_ptr
<base::SharedMemory
> shared_memory(new base::SharedMemory());
907 shared_memory
->CreateAndMapAnonymous(1);
908 base::SharedMemory
* shared_memory_ptr
= shared_memory
.get();
909 ResourceProvider::ResourceId id4
=
910 child_resource_provider_
->CreateResourceFromTextureMailbox(
911 TextureMailbox(shared_memory_ptr
, gfx::Size(1, 1)),
912 SingleReleaseCallback::Create(base::Bind(
913 &SharedMemoryReleaseCallback
, base::Passed(&shared_memory
))));
915 ReturnedResourceArray returned_to_child
;
917 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
919 // Transfer some resources to the parent.
920 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
921 resource_ids_to_transfer
.push_back(id1
);
922 resource_ids_to_transfer
.push_back(id2
);
923 resource_ids_to_transfer
.push_back(id3
);
924 resource_ids_to_transfer
.push_back(id4
);
925 TransferableResourceArray list
;
926 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
928 ASSERT_EQ(4u, list
.size());
929 EXPECT_EQ(0u, list
[0].mailbox_holder
.sync_point
);
930 EXPECT_EQ(0u, list
[1].mailbox_holder
.sync_point
);
931 EXPECT_EQ(0u, list
[2].mailbox_holder
.sync_point
);
932 EXPECT_EQ(0u, list
[3].mailbox_holder
.sync_point
);
933 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
934 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
935 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id3
));
936 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id4
));
937 resource_provider_
->ReceiveFromChild(child_id
, list
);
938 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
939 resource_ids_to_transfer
);
942 EXPECT_EQ(4u, resource_provider_
->num_resources());
943 ResourceProvider::ResourceIdMap resource_map
=
944 resource_provider_
->GetChildToParentMap(child_id
);
945 ResourceProvider::ResourceId mapped_id1
= resource_map
[id1
];
946 ResourceProvider::ResourceId mapped_id2
= resource_map
[id2
];
947 ResourceProvider::ResourceId mapped_id3
= resource_map
[id3
];
948 ResourceProvider::ResourceId mapped_id4
= resource_map
[id4
];
949 EXPECT_NE(0u, mapped_id1
);
950 EXPECT_NE(0u, mapped_id2
);
951 EXPECT_NE(0u, mapped_id3
);
952 EXPECT_NE(0u, mapped_id4
);
953 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id1
));
954 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id2
));
955 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id3
));
956 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id4
));
958 uint8_t result
[4] = { 0 };
960 resource_provider_
.get(), context(), mapped_id1
, size
, format
, result
);
961 EXPECT_EQ(0, memcmp(data1
, result
, pixel_size
));
964 resource_provider_
.get(), context(), mapped_id2
, size
, format
, result
);
965 EXPECT_EQ(0, memcmp(data2
, result
, pixel_size
));
968 resource_provider_
.get(), context(), mapped_id3
, size
, format
, result
);
969 EXPECT_EQ(0, memcmp(data3
, result
, pixel_size
));
972 // Check that transfering again the same resource from the child to the
974 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
975 resource_ids_to_transfer
.push_back(id1
);
976 resource_ids_to_transfer
.push_back(id2
);
977 resource_ids_to_transfer
.push_back(id3
);
978 TransferableResourceArray list
;
979 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
981 EXPECT_EQ(3u, list
.size());
982 EXPECT_EQ(id1
, list
[0].id
);
983 EXPECT_EQ(id2
, list
[1].id
);
984 EXPECT_EQ(id3
, list
[2].id
);
985 ReturnedResourceArray returned
;
986 TransferableResource::ReturnResources(list
, &returned
);
987 child_resource_provider_
->ReceiveReturnsFromParent(returned
);
988 // ids were exported twice, we returned them only once, they should still
990 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
991 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
992 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id3
));
995 EXPECT_EQ(0u, returned_to_child
.size());
997 // Transfer resources back from the parent to the child. Set no resources as
999 ResourceProvider::ResourceIdArray no_resources
;
1000 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
1002 ASSERT_EQ(4u, returned_to_child
.size());
1003 EXPECT_EQ(0u, returned_to_child
[0].sync_point
);
1004 EXPECT_EQ(0u, returned_to_child
[1].sync_point
);
1005 EXPECT_EQ(0u, returned_to_child
[2].sync_point
);
1006 EXPECT_EQ(0u, returned_to_child
[3].sync_point
);
1007 std::set
<ResourceProvider::ResourceId
> expected_ids
;
1008 expected_ids
.insert(id1
);
1009 expected_ids
.insert(id2
);
1010 expected_ids
.insert(id3
);
1011 expected_ids
.insert(id4
);
1012 std::set
<ResourceProvider::ResourceId
> returned_ids
;
1013 for (unsigned i
= 0; i
< 4; i
++)
1014 returned_ids
.insert(returned_to_child
[i
].id
);
1015 EXPECT_EQ(expected_ids
, returned_ids
);
1016 EXPECT_FALSE(returned_to_child
[0].lost
);
1017 EXPECT_FALSE(returned_to_child
[1].lost
);
1018 EXPECT_FALSE(returned_to_child
[2].lost
);
1019 EXPECT_FALSE(returned_to_child
[3].lost
);
1020 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
1021 returned_to_child
.clear();
1023 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id1
));
1024 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id2
));
1025 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id3
));
1026 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id4
));
1029 ResourceProvider::ScopedReadLockSoftware
lock(
1030 child_resource_provider_
.get(), id1
);
1031 const SkBitmap
* sk_bitmap
= lock
.sk_bitmap();
1032 EXPECT_EQ(sk_bitmap
->width(), size
.width());
1033 EXPECT_EQ(sk_bitmap
->height(), size
.height());
1034 EXPECT_EQ(0, memcmp(data1
, sk_bitmap
->getPixels(), pixel_size
));
1037 ResourceProvider::ScopedReadLockSoftware
lock(
1038 child_resource_provider_
.get(), id2
);
1039 const SkBitmap
* sk_bitmap
= lock
.sk_bitmap();
1040 EXPECT_EQ(sk_bitmap
->width(), size
.width());
1041 EXPECT_EQ(sk_bitmap
->height(), size
.height());
1042 EXPECT_EQ(0, memcmp(data2
, sk_bitmap
->getPixels(), pixel_size
));
1045 ResourceProvider::ScopedReadLockSoftware
lock(
1046 child_resource_provider_
.get(), id3
);
1047 const SkBitmap
* sk_bitmap
= lock
.sk_bitmap();
1048 EXPECT_EQ(sk_bitmap
->width(), size
.width());
1049 EXPECT_EQ(sk_bitmap
->height(), size
.height());
1050 EXPECT_EQ(0, memcmp(data3
, sk_bitmap
->getPixels(), pixel_size
));
1053 // Transfer resources to the parent again.
1054 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1055 resource_ids_to_transfer
.push_back(id1
);
1056 resource_ids_to_transfer
.push_back(id2
);
1057 resource_ids_to_transfer
.push_back(id3
);
1058 resource_ids_to_transfer
.push_back(id4
);
1059 TransferableResourceArray list
;
1060 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1062 ASSERT_EQ(4u, list
.size());
1063 EXPECT_EQ(id1
, list
[0].id
);
1064 EXPECT_EQ(id2
, list
[1].id
);
1065 EXPECT_EQ(id3
, list
[2].id
);
1066 EXPECT_EQ(id4
, list
[3].id
);
1067 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
1068 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
1069 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id3
));
1070 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id4
));
1071 resource_provider_
->ReceiveFromChild(child_id
, list
);
1072 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
1073 resource_ids_to_transfer
);
1076 EXPECT_EQ(0u, returned_to_child
.size());
1078 EXPECT_EQ(4u, resource_provider_
->num_resources());
1079 resource_provider_
->DestroyChild(child_id
);
1080 EXPECT_EQ(0u, resource_provider_
->num_resources());
1082 ASSERT_EQ(4u, returned_to_child
.size());
1083 EXPECT_EQ(0u, returned_to_child
[0].sync_point
);
1084 EXPECT_EQ(0u, returned_to_child
[1].sync_point
);
1085 EXPECT_EQ(0u, returned_to_child
[2].sync_point
);
1086 EXPECT_EQ(0u, returned_to_child
[3].sync_point
);
1087 std::set
<ResourceProvider::ResourceId
> expected_ids
;
1088 expected_ids
.insert(id1
);
1089 expected_ids
.insert(id2
);
1090 expected_ids
.insert(id3
);
1091 expected_ids
.insert(id4
);
1092 std::set
<ResourceProvider::ResourceId
> returned_ids
;
1093 for (unsigned i
= 0; i
< 4; i
++)
1094 returned_ids
.insert(returned_to_child
[i
].id
);
1095 EXPECT_EQ(expected_ids
, returned_ids
);
1096 EXPECT_FALSE(returned_to_child
[0].lost
);
1097 EXPECT_FALSE(returned_to_child
[1].lost
);
1098 EXPECT_FALSE(returned_to_child
[2].lost
);
1099 EXPECT_FALSE(returned_to_child
[3].lost
);
1102 TEST_P(ResourceProviderTest
, TransferGLToSoftware
) {
1103 if (GetParam() != ResourceProvider::Bitmap
)
1106 scoped_ptr
<ResourceProviderContext
> child_context_owned(
1107 ResourceProviderContext::Create(shared_data_
.get()));
1109 FakeOutputSurfaceClient child_output_surface_client
;
1110 scoped_ptr
<OutputSurface
> child_output_surface(FakeOutputSurface::Create3d(
1111 child_context_owned
.PassAs
<TestWebGraphicsContext3D
>()));
1112 CHECK(child_output_surface
->BindToClient(&child_output_surface_client
));
1114 scoped_ptr
<ResourceProvider
> child_resource_provider(ResourceProvider::Create(
1115 child_output_surface
.get(), shared_bitmap_manager_
.get(), 0, false, 1));
1117 gfx::Size
size(1, 1);
1118 ResourceFormat format
= RGBA_8888
;
1119 size_t pixel_size
= TextureSizeBytes(size
, format
);
1120 ASSERT_EQ(4U, pixel_size
);
1122 ResourceProvider::ResourceId id1
= child_resource_provider
->CreateResource(
1123 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureUsageAny
, format
);
1124 uint8_t data1
[4] = { 1, 2, 3, 4 };
1125 gfx::Rect
rect(size
);
1126 child_resource_provider
->SetPixels(id1
, data1
, rect
, rect
, gfx::Vector2d());
1128 ReturnedResourceArray returned_to_child
;
1130 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1132 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1133 resource_ids_to_transfer
.push_back(id1
);
1134 TransferableResourceArray list
;
1135 child_resource_provider
->PrepareSendToParent(resource_ids_to_transfer
,
1137 ASSERT_EQ(1u, list
.size());
1138 EXPECT_NE(0u, list
[0].mailbox_holder
.sync_point
);
1139 EXPECT_EQ(static_cast<GLenum
>(GL_TEXTURE_2D
),
1140 list
[0].mailbox_holder
.texture_target
);
1141 EXPECT_TRUE(child_resource_provider
->InUseByConsumer(id1
));
1142 resource_provider_
->ReceiveFromChild(child_id
, list
);
1145 EXPECT_EQ(0u, resource_provider_
->num_resources());
1146 ASSERT_EQ(1u, returned_to_child
.size());
1147 EXPECT_EQ(returned_to_child
[0].id
, id1
);
1148 ResourceProvider::ResourceIdMap resource_map
=
1149 resource_provider_
->GetChildToParentMap(child_id
);
1150 ResourceProvider::ResourceId mapped_id1
= resource_map
[id1
];
1151 EXPECT_EQ(0u, mapped_id1
);
1153 resource_provider_
->DestroyChild(child_id
);
1154 EXPECT_EQ(0u, resource_provider_
->num_resources());
1156 ASSERT_EQ(1u, returned_to_child
.size());
1157 EXPECT_FALSE(returned_to_child
[0].lost
);
1160 TEST_P(ResourceProviderTest
, TransferInvalidSoftware
) {
1161 if (GetParam() != ResourceProvider::Bitmap
)
1164 gfx::Size
size(1, 1);
1165 ResourceFormat format
= RGBA_8888
;
1166 size_t pixel_size
= TextureSizeBytes(size
, format
);
1167 ASSERT_EQ(4U, pixel_size
);
1169 ResourceProvider::ResourceId id1
= child_resource_provider_
->CreateResource(
1170 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureUsageAny
, format
);
1171 uint8_t data1
[4] = { 1, 2, 3, 4 };
1172 gfx::Rect
rect(size
);
1173 child_resource_provider_
->SetPixels(id1
, data1
, rect
, rect
, gfx::Vector2d());
1175 ReturnedResourceArray returned_to_child
;
1177 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1179 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1180 resource_ids_to_transfer
.push_back(id1
);
1181 TransferableResourceArray list
;
1182 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1184 ASSERT_EQ(1u, list
.size());
1186 list
[0].mailbox_holder
.mailbox
.name
[1] = 5;
1187 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
1188 resource_provider_
->ReceiveFromChild(child_id
, list
);
1191 EXPECT_EQ(1u, resource_provider_
->num_resources());
1192 EXPECT_EQ(0u, returned_to_child
.size());
1194 ResourceProvider::ResourceIdMap resource_map
=
1195 resource_provider_
->GetChildToParentMap(child_id
);
1196 ResourceProvider::ResourceId mapped_id1
= resource_map
[id1
];
1197 EXPECT_NE(0u, mapped_id1
);
1199 ResourceProvider::ScopedReadLockSoftware
lock(resource_provider_
.get(),
1201 EXPECT_FALSE(lock
.valid());
1204 resource_provider_
->DestroyChild(child_id
);
1205 EXPECT_EQ(0u, resource_provider_
->num_resources());
1207 ASSERT_EQ(1u, returned_to_child
.size());
1208 EXPECT_FALSE(returned_to_child
[0].lost
);
1211 TEST_P(ResourceProviderTest
, DeleteExportedResources
) {
1212 gfx::Size
size(1, 1);
1213 ResourceFormat format
= RGBA_8888
;
1214 size_t pixel_size
= TextureSizeBytes(size
, format
);
1215 ASSERT_EQ(4U, pixel_size
);
1217 ResourceProvider::ResourceId id1
= child_resource_provider_
->CreateResource(
1218 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureUsageAny
, format
);
1219 uint8_t data1
[4] = { 1, 2, 3, 4 };
1220 gfx::Rect
rect(size
);
1221 child_resource_provider_
->SetPixels(id1
, data1
, rect
, rect
, gfx::Vector2d());
1223 ResourceProvider::ResourceId id2
= child_resource_provider_
->CreateResource(
1224 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureUsageAny
, format
);
1225 uint8_t data2
[4] = {5, 5, 5, 5};
1226 child_resource_provider_
->SetPixels(id2
, data2
, rect
, rect
, gfx::Vector2d());
1228 ReturnedResourceArray returned_to_child
;
1230 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1232 // Transfer some resources to the parent.
1233 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1234 resource_ids_to_transfer
.push_back(id1
);
1235 resource_ids_to_transfer
.push_back(id2
);
1236 TransferableResourceArray list
;
1237 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1239 ASSERT_EQ(2u, list
.size());
1240 if (GetParam() == ResourceProvider::GLTexture
) {
1241 EXPECT_NE(0u, list
[0].mailbox_holder
.sync_point
);
1242 EXPECT_NE(0u, list
[1].mailbox_holder
.sync_point
);
1244 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
1245 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
1246 resource_provider_
->ReceiveFromChild(child_id
, list
);
1247 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
1248 resource_ids_to_transfer
);
1251 EXPECT_EQ(2u, resource_provider_
->num_resources());
1252 ResourceProvider::ResourceIdMap resource_map
=
1253 resource_provider_
->GetChildToParentMap(child_id
);
1254 ResourceProvider::ResourceId mapped_id1
= resource_map
[id1
];
1255 ResourceProvider::ResourceId mapped_id2
= resource_map
[id2
];
1256 EXPECT_NE(0u, mapped_id1
);
1257 EXPECT_NE(0u, mapped_id2
);
1258 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id1
));
1259 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id2
));
1262 // The parent transfers the resources to the grandparent.
1263 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1264 resource_ids_to_transfer
.push_back(mapped_id1
);
1265 resource_ids_to_transfer
.push_back(mapped_id2
);
1266 TransferableResourceArray list
;
1267 resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
, &list
);
1269 ASSERT_EQ(2u, list
.size());
1270 if (GetParam() == ResourceProvider::GLTexture
) {
1271 EXPECT_NE(0u, list
[0].mailbox_holder
.sync_point
);
1272 EXPECT_NE(0u, list
[1].mailbox_holder
.sync_point
);
1274 EXPECT_TRUE(resource_provider_
->InUseByConsumer(id1
));
1275 EXPECT_TRUE(resource_provider_
->InUseByConsumer(id2
));
1277 // Release the resource in the parent. Set no resources as being in use. The
1278 // resources are exported so that can't be transferred back yet.
1279 ResourceProvider::ResourceIdArray no_resources
;
1280 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
1282 EXPECT_EQ(0u, returned_to_child
.size());
1283 EXPECT_EQ(2u, resource_provider_
->num_resources());
1285 // Return the resources from the grandparent to the parent. They should be
1286 // returned to the child then.
1287 EXPECT_EQ(2u, list
.size());
1288 EXPECT_EQ(mapped_id1
, list
[0].id
);
1289 EXPECT_EQ(mapped_id2
, list
[1].id
);
1290 ReturnedResourceArray returned
;
1291 TransferableResource::ReturnResources(list
, &returned
);
1292 resource_provider_
->ReceiveReturnsFromParent(returned
);
1294 EXPECT_EQ(0u, resource_provider_
->num_resources());
1295 ASSERT_EQ(2u, returned_to_child
.size());
1296 if (GetParam() == ResourceProvider::GLTexture
) {
1297 EXPECT_NE(0u, returned_to_child
[0].sync_point
);
1298 EXPECT_NE(0u, returned_to_child
[1].sync_point
);
1300 EXPECT_FALSE(returned_to_child
[0].lost
);
1301 EXPECT_FALSE(returned_to_child
[1].lost
);
1305 TEST_P(ResourceProviderTest
, DestroyChildWithExportedResources
) {
1306 gfx::Size
size(1, 1);
1307 ResourceFormat format
= RGBA_8888
;
1308 size_t pixel_size
= TextureSizeBytes(size
, format
);
1309 ASSERT_EQ(4U, pixel_size
);
1311 ResourceProvider::ResourceId id1
= child_resource_provider_
->CreateResource(
1312 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureUsageAny
, format
);
1313 uint8_t data1
[4] = {1, 2, 3, 4};
1314 gfx::Rect
rect(size
);
1315 child_resource_provider_
->SetPixels(id1
, data1
, rect
, rect
, gfx::Vector2d());
1317 ResourceProvider::ResourceId id2
= child_resource_provider_
->CreateResource(
1318 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureUsageAny
, format
);
1319 uint8_t data2
[4] = {5, 5, 5, 5};
1320 child_resource_provider_
->SetPixels(id2
, data2
, rect
, rect
, gfx::Vector2d());
1322 ReturnedResourceArray returned_to_child
;
1324 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1326 // Transfer some resources to the parent.
1327 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1328 resource_ids_to_transfer
.push_back(id1
);
1329 resource_ids_to_transfer
.push_back(id2
);
1330 TransferableResourceArray list
;
1331 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1333 ASSERT_EQ(2u, list
.size());
1334 if (GetParam() == ResourceProvider::GLTexture
) {
1335 EXPECT_NE(0u, list
[0].mailbox_holder
.sync_point
);
1336 EXPECT_NE(0u, list
[1].mailbox_holder
.sync_point
);
1338 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id1
));
1339 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id2
));
1340 resource_provider_
->ReceiveFromChild(child_id
, list
);
1341 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
1342 resource_ids_to_transfer
);
1345 EXPECT_EQ(2u, resource_provider_
->num_resources());
1346 ResourceProvider::ResourceIdMap resource_map
=
1347 resource_provider_
->GetChildToParentMap(child_id
);
1348 ResourceProvider::ResourceId mapped_id1
= resource_map
[id1
];
1349 ResourceProvider::ResourceId mapped_id2
= resource_map
[id2
];
1350 EXPECT_NE(0u, mapped_id1
);
1351 EXPECT_NE(0u, mapped_id2
);
1352 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id1
));
1353 EXPECT_FALSE(resource_provider_
->InUseByConsumer(id2
));
1356 // The parent transfers the resources to the grandparent.
1357 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1358 resource_ids_to_transfer
.push_back(mapped_id1
);
1359 resource_ids_to_transfer
.push_back(mapped_id2
);
1360 TransferableResourceArray list
;
1361 resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
, &list
);
1363 ASSERT_EQ(2u, list
.size());
1364 if (GetParam() == ResourceProvider::GLTexture
) {
1365 EXPECT_NE(0u, list
[0].mailbox_holder
.sync_point
);
1366 EXPECT_NE(0u, list
[1].mailbox_holder
.sync_point
);
1368 EXPECT_TRUE(resource_provider_
->InUseByConsumer(id1
));
1369 EXPECT_TRUE(resource_provider_
->InUseByConsumer(id2
));
1371 // Release the resource in the parent. Set no resources as being in use. The
1372 // resources are exported so that can't be transferred back yet.
1373 ResourceProvider::ResourceIdArray no_resources
;
1374 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
1376 // Destroy the child, the resources should not be returned yet.
1377 EXPECT_EQ(0u, returned_to_child
.size());
1378 EXPECT_EQ(2u, resource_provider_
->num_resources());
1380 resource_provider_
->DestroyChild(child_id
);
1382 EXPECT_EQ(2u, resource_provider_
->num_resources());
1383 ASSERT_EQ(0u, returned_to_child
.size());
1385 // Return a resource from the grandparent, it should be returned at this
1387 EXPECT_EQ(2u, list
.size());
1388 EXPECT_EQ(mapped_id1
, list
[0].id
);
1389 EXPECT_EQ(mapped_id2
, list
[1].id
);
1390 TransferableResourceArray return_list
;
1391 return_list
.push_back(list
[1]);
1393 ReturnedResourceArray returned
;
1394 TransferableResource::ReturnResources(return_list
, &returned
);
1395 resource_provider_
->ReceiveReturnsFromParent(returned
);
1397 EXPECT_EQ(1u, resource_provider_
->num_resources());
1398 ASSERT_EQ(1u, returned_to_child
.size());
1399 if (GetParam() == ResourceProvider::GLTexture
) {
1400 EXPECT_NE(0u, returned_to_child
[0].sync_point
);
1402 EXPECT_FALSE(returned_to_child
[0].lost
);
1403 returned_to_child
.clear();
1405 // Destroy the parent resource provider. The resource that's left should be
1406 // lost at this point, and returned.
1407 resource_provider_
.reset();
1408 ASSERT_EQ(1u, returned_to_child
.size());
1409 if (GetParam() == ResourceProvider::GLTexture
) {
1410 EXPECT_NE(0u, returned_to_child
[0].sync_point
);
1412 EXPECT_TRUE(returned_to_child
[0].lost
);
1416 TEST_P(ResourceProviderTest
, DeleteTransferredResources
) {
1417 gfx::Size
size(1, 1);
1418 ResourceFormat format
= RGBA_8888
;
1419 size_t pixel_size
= TextureSizeBytes(size
, format
);
1420 ASSERT_EQ(4U, pixel_size
);
1422 ResourceProvider::ResourceId id
= child_resource_provider_
->CreateResource(
1423 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureUsageAny
, format
);
1424 uint8_t data
[4] = { 1, 2, 3, 4 };
1425 gfx::Rect
rect(size
);
1426 child_resource_provider_
->SetPixels(id
, data
, rect
, rect
, gfx::Vector2d());
1428 ReturnedResourceArray returned_to_child
;
1430 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1432 // Transfer some resource to the parent.
1433 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1434 resource_ids_to_transfer
.push_back(id
);
1435 TransferableResourceArray list
;
1436 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1438 ASSERT_EQ(1u, list
.size());
1439 if (GetParam() == ResourceProvider::GLTexture
)
1440 EXPECT_NE(0u, list
[0].mailbox_holder
.sync_point
);
1441 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id
));
1442 resource_provider_
->ReceiveFromChild(child_id
, list
);
1443 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
1444 resource_ids_to_transfer
);
1447 // Delete textures in the child, while they are transfered.
1448 child_resource_provider_
->DeleteResource(id
);
1449 EXPECT_EQ(1u, child_resource_provider_
->num_resources());
1451 EXPECT_EQ(0u, returned_to_child
.size());
1453 // Transfer resources back from the parent to the child. Set no resources as
1455 ResourceProvider::ResourceIdArray no_resources
;
1456 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
1458 ASSERT_EQ(1u, returned_to_child
.size());
1459 if (GetParam() == ResourceProvider::GLTexture
)
1460 EXPECT_NE(0u, returned_to_child
[0].sync_point
);
1461 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
1463 EXPECT_EQ(0u, child_resource_provider_
->num_resources());
1466 TEST_P(ResourceProviderTest
, UnuseTransferredResources
) {
1467 gfx::Size
size(1, 1);
1468 ResourceFormat format
= RGBA_8888
;
1469 size_t pixel_size
= TextureSizeBytes(size
, format
);
1470 ASSERT_EQ(4U, pixel_size
);
1472 ResourceProvider::ResourceId id
= child_resource_provider_
->CreateResource(
1473 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureUsageAny
, format
);
1474 uint8_t data
[4] = {1, 2, 3, 4};
1475 gfx::Rect
rect(size
);
1476 child_resource_provider_
->SetPixels(id
, data
, rect
, rect
, gfx::Vector2d());
1478 ReturnedResourceArray returned_to_child
;
1480 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1481 const ResourceProvider::ResourceIdMap
& map
=
1482 resource_provider_
->GetChildToParentMap(child_id
);
1484 // Transfer some resource to the parent.
1485 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1486 resource_ids_to_transfer
.push_back(id
);
1487 TransferableResourceArray list
;
1488 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1490 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id
));
1491 resource_provider_
->ReceiveFromChild(child_id
, list
);
1492 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
1493 resource_ids_to_transfer
);
1495 TransferableResourceArray sent_to_top_level
;
1497 // Parent transfers to top-level.
1498 ASSERT_TRUE(map
.find(id
) != map
.end());
1499 ResourceProvider::ResourceId parent_id
= map
.find(id
)->second
;
1500 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1501 resource_ids_to_transfer
.push_back(parent_id
);
1502 resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1503 &sent_to_top_level
);
1504 EXPECT_TRUE(resource_provider_
->InUseByConsumer(parent_id
));
1507 // Stop using resource.
1508 ResourceProvider::ResourceIdArray empty
;
1509 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, empty
);
1510 // Resource is not yet returned to the child, since it's in use by the
1512 EXPECT_TRUE(returned_to_child
.empty());
1515 // Send the resource to the parent again.
1516 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1517 resource_ids_to_transfer
.push_back(id
);
1518 TransferableResourceArray list
;
1519 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1521 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(id
));
1522 resource_provider_
->ReceiveFromChild(child_id
, list
);
1523 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
1524 resource_ids_to_transfer
);
1527 // Receive returns back from top-level.
1528 ReturnedResourceArray returned
;
1529 TransferableResource::ReturnResources(sent_to_top_level
, &returned
);
1530 resource_provider_
->ReceiveReturnsFromParent(returned
);
1531 // Resource is still not yet returned to the child, since it's declared used
1533 EXPECT_TRUE(returned_to_child
.empty());
1534 ASSERT_TRUE(map
.find(id
) != map
.end());
1535 ResourceProvider::ResourceId parent_id
= map
.find(id
)->second
;
1536 EXPECT_FALSE(resource_provider_
->InUseByConsumer(parent_id
));
1539 sent_to_top_level
.clear();
1540 // Parent transfers again to top-level.
1541 ASSERT_TRUE(map
.find(id
) != map
.end());
1542 ResourceProvider::ResourceId parent_id
= map
.find(id
)->second
;
1543 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1544 resource_ids_to_transfer
.push_back(parent_id
);
1545 resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1546 &sent_to_top_level
);
1547 EXPECT_TRUE(resource_provider_
->InUseByConsumer(parent_id
));
1550 // Receive returns back from top-level.
1551 ReturnedResourceArray returned
;
1552 TransferableResource::ReturnResources(sent_to_top_level
, &returned
);
1553 resource_provider_
->ReceiveReturnsFromParent(returned
);
1554 // Resource is still not yet returned to the child, since it's still
1555 // declared used in the parent.
1556 EXPECT_TRUE(returned_to_child
.empty());
1557 ASSERT_TRUE(map
.find(id
) != map
.end());
1558 ResourceProvider::ResourceId parent_id
= map
.find(id
)->second
;
1559 EXPECT_FALSE(resource_provider_
->InUseByConsumer(parent_id
));
1562 // Stop using resource.
1563 ResourceProvider::ResourceIdArray empty
;
1564 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, empty
);
1565 // Resource should have been returned to the child, since it's no longer in
1566 // use by the top-level.
1567 ASSERT_EQ(1u, returned_to_child
.size());
1568 EXPECT_EQ(id
, returned_to_child
[0].id
);
1569 EXPECT_EQ(2, returned_to_child
[0].count
);
1570 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
1571 returned_to_child
.clear();
1572 EXPECT_FALSE(child_resource_provider_
->InUseByConsumer(id
));
1576 class ResourceProviderTestTextureFilters
: public ResourceProviderTest
{
1578 static void RunTest(GLenum child_filter
, GLenum parent_filter
) {
1579 scoped_ptr
<TextureStateTrackingContext
> child_context_owned(
1580 new TextureStateTrackingContext
);
1581 TextureStateTrackingContext
* child_context
= child_context_owned
.get();
1583 FakeOutputSurfaceClient child_output_surface_client
;
1584 scoped_ptr
<OutputSurface
> child_output_surface(FakeOutputSurface::Create3d(
1585 child_context_owned
.PassAs
<TestWebGraphicsContext3D
>()));
1586 CHECK(child_output_surface
->BindToClient(&child_output_surface_client
));
1587 scoped_ptr
<SharedBitmapManager
> shared_bitmap_manager(
1588 new TestSharedBitmapManager());
1590 scoped_ptr
<ResourceProvider
> child_resource_provider(
1591 ResourceProvider::Create(child_output_surface
.get(),
1592 shared_bitmap_manager
.get(),
1597 scoped_ptr
<TextureStateTrackingContext
> parent_context_owned(
1598 new TextureStateTrackingContext
);
1599 TextureStateTrackingContext
* parent_context
= parent_context_owned
.get();
1601 FakeOutputSurfaceClient parent_output_surface_client
;
1602 scoped_ptr
<OutputSurface
> parent_output_surface(FakeOutputSurface::Create3d(
1603 parent_context_owned
.PassAs
<TestWebGraphicsContext3D
>()));
1604 CHECK(parent_output_surface
->BindToClient(&parent_output_surface_client
));
1606 scoped_ptr
<ResourceProvider
> parent_resource_provider(
1607 ResourceProvider::Create(parent_output_surface
.get(),
1608 shared_bitmap_manager
.get(),
1613 gfx::Size
size(1, 1);
1614 ResourceFormat format
= RGBA_8888
;
1615 int child_texture_id
= 1;
1616 int parent_texture_id
= 2;
1618 size_t pixel_size
= TextureSizeBytes(size
, format
);
1619 ASSERT_EQ(4U, pixel_size
);
1621 ResourceProvider::ResourceId id
= child_resource_provider
->CreateResource(
1622 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureUsageAny
, format
);
1624 // The new texture is created with GL_LINEAR.
1625 EXPECT_CALL(*child_context
, bindTexture(GL_TEXTURE_2D
, child_texture_id
))
1626 .Times(2); // Once to create and once to allocate.
1627 EXPECT_CALL(*child_context
,
1628 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
));
1629 EXPECT_CALL(*child_context
,
1630 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
));
1633 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
));
1636 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
));
1637 EXPECT_CALL(*child_context
,
1638 texParameteri(GL_TEXTURE_2D
,
1639 GL_TEXTURE_POOL_CHROMIUM
,
1640 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
));
1641 child_resource_provider
->AllocateForTesting(id
);
1642 Mock::VerifyAndClearExpectations(child_context
);
1644 uint8_t data
[4] = { 1, 2, 3, 4 };
1645 gfx::Rect
rect(size
);
1647 EXPECT_CALL(*child_context
, bindTexture(GL_TEXTURE_2D
, child_texture_id
));
1648 child_resource_provider
->SetPixels(id
, data
, rect
, rect
, gfx::Vector2d());
1649 Mock::VerifyAndClearExpectations(child_context
);
1651 // The texture is set to |child_filter| in the child.
1652 EXPECT_CALL(*child_context
, bindTexture(GL_TEXTURE_2D
, child_texture_id
));
1653 if (child_filter
!= GL_LINEAR
) {
1656 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, child_filter
));
1659 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, child_filter
));
1661 SetResourceFilter(child_resource_provider
.get(), id
, child_filter
);
1662 Mock::VerifyAndClearExpectations(child_context
);
1664 ReturnedResourceArray returned_to_child
;
1665 int child_id
= parent_resource_provider
->CreateChild(
1666 GetReturnCallback(&returned_to_child
));
1668 // Transfer some resource to the parent.
1669 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1670 resource_ids_to_transfer
.push_back(id
);
1671 TransferableResourceArray list
;
1673 EXPECT_CALL(*child_context
, bindTexture(GL_TEXTURE_2D
, child_texture_id
));
1674 EXPECT_CALL(*child_context
,
1675 produceTextureCHROMIUM(GL_TEXTURE_2D
, _
));
1676 EXPECT_CALL(*child_context
, insertSyncPoint());
1677 child_resource_provider
->PrepareSendToParent(resource_ids_to_transfer
,
1679 Mock::VerifyAndClearExpectations(child_context
);
1681 ASSERT_EQ(1u, list
.size());
1682 EXPECT_EQ(static_cast<unsigned>(child_filter
), list
[0].filter
);
1684 EXPECT_CALL(*parent_context
,
1685 bindTexture(GL_TEXTURE_2D
, parent_texture_id
));
1686 EXPECT_CALL(*parent_context
, consumeTextureCHROMIUM(GL_TEXTURE_2D
, _
));
1687 parent_resource_provider
->ReceiveFromChild(child_id
, list
);
1689 ResourceProvider::ScopedReadLockGL
lock(parent_resource_provider
.get(),
1692 Mock::VerifyAndClearExpectations(parent_context
);
1694 parent_resource_provider
->DeclareUsedResourcesFromChild(
1695 child_id
, resource_ids_to_transfer
);
1696 Mock::VerifyAndClearExpectations(parent_context
);
1698 ResourceProvider::ResourceIdMap resource_map
=
1699 parent_resource_provider
->GetChildToParentMap(child_id
);
1700 ResourceProvider::ResourceId mapped_id
= resource_map
[id
];
1701 EXPECT_NE(0u, mapped_id
);
1703 // The texture is set to |parent_filter| in the parent.
1704 EXPECT_CALL(*parent_context
, bindTexture(GL_TEXTURE_2D
, parent_texture_id
));
1707 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, parent_filter
));
1710 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, parent_filter
));
1711 SetResourceFilter(parent_resource_provider
.get(), mapped_id
, parent_filter
);
1712 Mock::VerifyAndClearExpectations(parent_context
);
1714 // The texture should be reset to |child_filter| in the parent when it is
1715 // returned, since that is how it was received.
1716 EXPECT_CALL(*parent_context
, bindTexture(GL_TEXTURE_2D
, parent_texture_id
));
1719 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, child_filter
));
1722 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, child_filter
));
1725 EXPECT_EQ(0u, returned_to_child
.size());
1727 // Transfer resources back from the parent to the child. Set no resources
1729 ResourceProvider::ResourceIdArray no_resources
;
1730 EXPECT_CALL(*parent_context
, insertSyncPoint());
1731 parent_resource_provider
->DeclareUsedResourcesFromChild(child_id
,
1733 Mock::VerifyAndClearExpectations(parent_context
);
1735 ASSERT_EQ(1u, returned_to_child
.size());
1736 child_resource_provider
->ReceiveReturnsFromParent(returned_to_child
);
1739 // The child remembers the texture filter is set to |child_filter|.
1740 EXPECT_CALL(*child_context
, bindTexture(GL_TEXTURE_2D
, child_texture_id
));
1741 SetResourceFilter(child_resource_provider
.get(), id
, child_filter
);
1742 Mock::VerifyAndClearExpectations(child_context
);
1746 TEST_P(ResourceProviderTest
, TextureFilters_ChildNearestParentLinear
) {
1747 if (GetParam() != ResourceProvider::GLTexture
)
1749 ResourceProviderTestTextureFilters::RunTest(GL_NEAREST
, GL_LINEAR
);
1752 TEST_P(ResourceProviderTest
, TextureFilters_ChildLinearParentNearest
) {
1753 if (GetParam() != ResourceProvider::GLTexture
)
1755 ResourceProviderTestTextureFilters::RunTest(GL_LINEAR
, GL_NEAREST
);
1758 TEST_P(ResourceProviderTest
, TransferMailboxResources
) {
1759 // Other mailbox transfers tested elsewhere.
1760 if (GetParam() != ResourceProvider::GLTexture
)
1762 unsigned texture
= context()->createTexture();
1763 context()->bindTexture(GL_TEXTURE_2D
, texture
);
1764 uint8_t data
[4] = { 1, 2, 3, 4 };
1765 context()->texImage2D(
1766 GL_TEXTURE_2D
, 0, GL_RGBA
, 1, 1, 0, GL_RGBA
, GL_UNSIGNED_BYTE
, &data
);
1767 gpu::Mailbox mailbox
;
1768 context()->genMailboxCHROMIUM(mailbox
.name
);
1769 context()->produceTextureCHROMIUM(GL_TEXTURE_2D
, mailbox
.name
);
1770 uint32 sync_point
= context()->insertSyncPoint();
1772 // All the logic below assumes that the sync points are all positive.
1773 EXPECT_LT(0u, sync_point
);
1775 uint32 release_sync_point
= 0;
1776 bool lost_resource
= false;
1777 ReleaseCallback callback
=
1778 base::Bind(ReleaseTextureMailbox
, &release_sync_point
, &lost_resource
);
1779 ResourceProvider::ResourceId resource
=
1780 resource_provider_
->CreateResourceFromTextureMailbox(
1781 TextureMailbox(mailbox
, GL_TEXTURE_2D
, sync_point
),
1782 SingleReleaseCallback::Create(callback
));
1783 EXPECT_EQ(1u, context()->NumTextures());
1784 EXPECT_EQ(0u, release_sync_point
);
1786 // Transfer the resource, expect the sync points to be consistent.
1787 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1788 resource_ids_to_transfer
.push_back(resource
);
1789 TransferableResourceArray list
;
1790 resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
, &list
);
1791 ASSERT_EQ(1u, list
.size());
1792 EXPECT_LE(sync_point
, list
[0].mailbox_holder
.sync_point
);
1794 memcmp(mailbox
.name
,
1795 list
[0].mailbox_holder
.mailbox
.name
,
1796 sizeof(mailbox
.name
)));
1797 EXPECT_EQ(0u, release_sync_point
);
1799 context()->waitSyncPoint(list
[0].mailbox_holder
.sync_point
);
1800 unsigned other_texture
= context()->createTexture();
1801 context()->bindTexture(GL_TEXTURE_2D
, other_texture
);
1802 context()->consumeTextureCHROMIUM(GL_TEXTURE_2D
, mailbox
.name
);
1803 uint8_t test_data
[4] = { 0 };
1804 context()->GetPixels(
1805 gfx::Size(1, 1), RGBA_8888
, test_data
);
1806 EXPECT_EQ(0, memcmp(data
, test_data
, sizeof(data
)));
1807 context()->produceTextureCHROMIUM(GL_TEXTURE_2D
, mailbox
.name
);
1808 context()->deleteTexture(other_texture
);
1809 list
[0].mailbox_holder
.sync_point
= context()->insertSyncPoint();
1810 EXPECT_LT(0u, list
[0].mailbox_holder
.sync_point
);
1812 // Receive the resource, then delete it, expect the sync points to be
1814 ReturnedResourceArray returned
;
1815 TransferableResource::ReturnResources(list
, &returned
);
1816 resource_provider_
->ReceiveReturnsFromParent(returned
);
1817 EXPECT_EQ(1u, context()->NumTextures());
1818 EXPECT_EQ(0u, release_sync_point
);
1820 resource_provider_
->DeleteResource(resource
);
1821 EXPECT_LE(list
[0].mailbox_holder
.sync_point
, release_sync_point
);
1822 EXPECT_FALSE(lost_resource
);
1825 // We're going to do the same thing as above, but testing the case where we
1826 // delete the resource before we receive it back.
1827 sync_point
= release_sync_point
;
1828 EXPECT_LT(0u, sync_point
);
1829 release_sync_point
= 0;
1830 resource
= resource_provider_
->CreateResourceFromTextureMailbox(
1831 TextureMailbox(mailbox
, GL_TEXTURE_2D
, sync_point
),
1832 SingleReleaseCallback::Create(callback
));
1833 EXPECT_EQ(1u, context()->NumTextures());
1834 EXPECT_EQ(0u, release_sync_point
);
1836 // Transfer the resource, expect the sync points to be consistent.
1837 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1838 resource_ids_to_transfer
.push_back(resource
);
1839 TransferableResourceArray list
;
1840 resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
, &list
);
1841 ASSERT_EQ(1u, list
.size());
1842 EXPECT_LE(sync_point
, list
[0].mailbox_holder
.sync_point
);
1844 memcmp(mailbox
.name
,
1845 list
[0].mailbox_holder
.mailbox
.name
,
1846 sizeof(mailbox
.name
)));
1847 EXPECT_EQ(0u, release_sync_point
);
1849 context()->waitSyncPoint(list
[0].mailbox_holder
.sync_point
);
1850 unsigned other_texture
= context()->createTexture();
1851 context()->bindTexture(GL_TEXTURE_2D
, other_texture
);
1852 context()->consumeTextureCHROMIUM(GL_TEXTURE_2D
, mailbox
.name
);
1853 uint8_t test_data
[4] = { 0 };
1854 context()->GetPixels(
1855 gfx::Size(1, 1), RGBA_8888
, test_data
);
1856 EXPECT_EQ(0, memcmp(data
, test_data
, sizeof(data
)));
1857 context()->produceTextureCHROMIUM(GL_TEXTURE_2D
, mailbox
.name
);
1858 context()->deleteTexture(other_texture
);
1859 list
[0].mailbox_holder
.sync_point
= context()->insertSyncPoint();
1860 EXPECT_LT(0u, list
[0].mailbox_holder
.sync_point
);
1862 // Delete the resource, which shouldn't do anything.
1863 resource_provider_
->DeleteResource(resource
);
1864 EXPECT_EQ(1u, context()->NumTextures());
1865 EXPECT_EQ(0u, release_sync_point
);
1867 // Then receive the resource which should release the mailbox, expect the
1868 // sync points to be consistent.
1869 ReturnedResourceArray returned
;
1870 TransferableResource::ReturnResources(list
, &returned
);
1871 resource_provider_
->ReceiveReturnsFromParent(returned
);
1872 EXPECT_LE(list
[0].mailbox_holder
.sync_point
, release_sync_point
);
1873 EXPECT_FALSE(lost_resource
);
1876 context()->waitSyncPoint(release_sync_point
);
1877 context()->bindTexture(GL_TEXTURE_2D
, texture
);
1878 context()->consumeTextureCHROMIUM(GL_TEXTURE_2D
, mailbox
.name
);
1879 context()->deleteTexture(texture
);
1882 TEST_P(ResourceProviderTest
, LostResourceInParent
) {
1883 gfx::Size
size(1, 1);
1884 ResourceFormat format
= RGBA_8888
;
1885 ResourceProvider::ResourceId resource
=
1886 child_resource_provider_
->CreateResource(
1887 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureUsageAny
, format
);
1888 child_resource_provider_
->AllocateForTesting(resource
);
1889 // Expect a GL resource to be lost.
1890 bool should_lose_resource
= GetParam() == ResourceProvider::GLTexture
;
1892 ReturnedResourceArray returned_to_child
;
1894 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1896 // Transfer the resource to the parent.
1897 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1898 resource_ids_to_transfer
.push_back(resource
);
1899 TransferableResourceArray list
;
1900 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1902 EXPECT_EQ(1u, list
.size());
1904 resource_provider_
->ReceiveFromChild(child_id
, list
);
1905 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
1906 resource_ids_to_transfer
);
1909 // Lose the output surface in the parent.
1910 resource_provider_
->DidLoseOutputSurface();
1913 EXPECT_EQ(0u, returned_to_child
.size());
1915 // Transfer resources back from the parent to the child. Set no resources as
1917 ResourceProvider::ResourceIdArray no_resources
;
1918 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
1920 // Expect a GL resource to be lost.
1921 ASSERT_EQ(1u, returned_to_child
.size());
1922 EXPECT_EQ(should_lose_resource
, returned_to_child
[0].lost
);
1923 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
1924 returned_to_child
.clear();
1927 // A GL resource should be lost.
1928 EXPECT_EQ(should_lose_resource
, child_resource_provider_
->IsLost(resource
));
1930 // Lost resources stay in use in the parent forever.
1931 EXPECT_EQ(should_lose_resource
,
1932 child_resource_provider_
->InUseByConsumer(resource
));
1935 TEST_P(ResourceProviderTest
, LostResourceInGrandParent
) {
1936 gfx::Size
size(1, 1);
1937 ResourceFormat format
= RGBA_8888
;
1938 ResourceProvider::ResourceId resource
=
1939 child_resource_provider_
->CreateResource(
1940 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureUsageAny
, format
);
1941 child_resource_provider_
->AllocateForTesting(resource
);
1943 ReturnedResourceArray returned_to_child
;
1945 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
1947 // Transfer the resource to the parent.
1948 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1949 resource_ids_to_transfer
.push_back(resource
);
1950 TransferableResourceArray list
;
1951 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
1953 EXPECT_EQ(1u, list
.size());
1955 resource_provider_
->ReceiveFromChild(child_id
, list
);
1956 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
1957 resource_ids_to_transfer
);
1961 ResourceProvider::ResourceIdMap resource_map
=
1962 resource_provider_
->GetChildToParentMap(child_id
);
1963 ResourceProvider::ResourceId parent_resource
= resource_map
[resource
];
1964 EXPECT_NE(0u, parent_resource
);
1966 // Transfer to a grandparent.
1967 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
1968 resource_ids_to_transfer
.push_back(parent_resource
);
1969 TransferableResourceArray list
;
1970 resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
, &list
);
1972 // Receive back a lost resource from the grandparent.
1973 EXPECT_EQ(1u, list
.size());
1974 EXPECT_EQ(parent_resource
, list
[0].id
);
1975 ReturnedResourceArray returned
;
1976 TransferableResource::ReturnResources(list
, &returned
);
1977 EXPECT_EQ(1u, returned
.size());
1978 EXPECT_EQ(parent_resource
, returned
[0].id
);
1979 returned
[0].lost
= true;
1980 resource_provider_
->ReceiveReturnsFromParent(returned
);
1982 // The resource should be lost.
1983 EXPECT_TRUE(resource_provider_
->IsLost(parent_resource
));
1985 // Lost resources stay in use in the parent forever.
1986 EXPECT_TRUE(resource_provider_
->InUseByConsumer(parent_resource
));
1990 EXPECT_EQ(0u, returned_to_child
.size());
1992 // Transfer resources back from the parent to the child. Set no resources as
1994 ResourceProvider::ResourceIdArray no_resources
;
1995 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
1997 // Expect the resource to be lost.
1998 ASSERT_EQ(1u, returned_to_child
.size());
1999 EXPECT_TRUE(returned_to_child
[0].lost
);
2000 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
2001 returned_to_child
.clear();
2004 // The resource should be lost.
2005 EXPECT_TRUE(child_resource_provider_
->IsLost(resource
));
2007 // Lost resources stay in use in the parent forever.
2008 EXPECT_TRUE(child_resource_provider_
->InUseByConsumer(resource
));
2011 TEST_P(ResourceProviderTest
, LostMailboxInParent
) {
2012 uint32 release_sync_point
= 0;
2013 bool lost_resource
= false;
2014 bool release_called
= false;
2015 uint32 sync_point
= 0;
2016 ResourceProvider::ResourceId resource
= CreateChildMailbox(
2017 &release_sync_point
, &lost_resource
, &release_called
, &sync_point
);
2019 ReturnedResourceArray returned_to_child
;
2021 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
2023 // Transfer the resource to the parent.
2024 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
2025 resource_ids_to_transfer
.push_back(resource
);
2026 TransferableResourceArray list
;
2027 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
2029 EXPECT_EQ(1u, list
.size());
2031 resource_provider_
->ReceiveFromChild(child_id
, list
);
2032 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
2033 resource_ids_to_transfer
);
2036 // Lose the output surface in the parent.
2037 resource_provider_
->DidLoseOutputSurface();
2040 EXPECT_EQ(0u, returned_to_child
.size());
2042 // Transfer resources back from the parent to the child. Set no resources as
2044 ResourceProvider::ResourceIdArray no_resources
;
2045 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
2047 ASSERT_EQ(1u, returned_to_child
.size());
2048 // Losing an output surface only loses hardware resources.
2049 EXPECT_EQ(returned_to_child
[0].lost
,
2050 GetParam() == ResourceProvider::GLTexture
);
2051 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
2052 returned_to_child
.clear();
2055 // Delete the resource in the child. Expect the resource to be lost if it's
2057 child_resource_provider_
->DeleteResource(resource
);
2058 EXPECT_EQ(lost_resource
, GetParam() == ResourceProvider::GLTexture
);
2061 TEST_P(ResourceProviderTest
, LostMailboxInGrandParent
) {
2062 uint32 release_sync_point
= 0;
2063 bool lost_resource
= false;
2064 bool release_called
= false;
2065 uint32 sync_point
= 0;
2066 ResourceProvider::ResourceId resource
= CreateChildMailbox(
2067 &release_sync_point
, &lost_resource
, &release_called
, &sync_point
);
2069 ReturnedResourceArray returned_to_child
;
2071 resource_provider_
->CreateChild(GetReturnCallback(&returned_to_child
));
2073 // Transfer the resource to the parent.
2074 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
2075 resource_ids_to_transfer
.push_back(resource
);
2076 TransferableResourceArray list
;
2077 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
2079 EXPECT_EQ(1u, list
.size());
2081 resource_provider_
->ReceiveFromChild(child_id
, list
);
2082 resource_provider_
->DeclareUsedResourcesFromChild(child_id
,
2083 resource_ids_to_transfer
);
2087 ResourceProvider::ResourceIdMap resource_map
=
2088 resource_provider_
->GetChildToParentMap(child_id
);
2089 ResourceProvider::ResourceId parent_resource
= resource_map
[resource
];
2090 EXPECT_NE(0u, parent_resource
);
2092 // Transfer to a grandparent.
2093 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
2094 resource_ids_to_transfer
.push_back(parent_resource
);
2095 TransferableResourceArray list
;
2096 resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
, &list
);
2098 // Receive back a lost resource from the grandparent.
2099 EXPECT_EQ(1u, list
.size());
2100 EXPECT_EQ(parent_resource
, list
[0].id
);
2101 ReturnedResourceArray returned
;
2102 TransferableResource::ReturnResources(list
, &returned
);
2103 EXPECT_EQ(1u, returned
.size());
2104 EXPECT_EQ(parent_resource
, returned
[0].id
);
2105 returned
[0].lost
= true;
2106 resource_provider_
->ReceiveReturnsFromParent(returned
);
2110 EXPECT_EQ(0u, returned_to_child
.size());
2112 // Transfer resources back from the parent to the child. Set no resources as
2114 ResourceProvider::ResourceIdArray no_resources
;
2115 resource_provider_
->DeclareUsedResourcesFromChild(child_id
, no_resources
);
2117 // Expect the resource to be lost.
2118 ASSERT_EQ(1u, returned_to_child
.size());
2119 EXPECT_TRUE(returned_to_child
[0].lost
);
2120 child_resource_provider_
->ReceiveReturnsFromParent(returned_to_child
);
2121 returned_to_child
.clear();
2124 // Delete the resource in the child. Expect the resource to be lost.
2125 child_resource_provider_
->DeleteResource(resource
);
2126 EXPECT_TRUE(lost_resource
);
2129 TEST_P(ResourceProviderTest
, Shutdown
) {
2130 uint32 release_sync_point
= 0;
2131 bool lost_resource
= false;
2132 bool release_called
= false;
2133 uint32 sync_point
= 0;
2135 &release_sync_point
, &lost_resource
, &release_called
, &sync_point
);
2137 EXPECT_EQ(0u, release_sync_point
);
2138 EXPECT_FALSE(lost_resource
);
2140 child_resource_provider_
.reset();
2142 if (GetParam() == ResourceProvider::GLTexture
) {
2143 EXPECT_LE(sync_point
, release_sync_point
);
2145 EXPECT_TRUE(release_called
);
2146 EXPECT_FALSE(lost_resource
);
2149 TEST_P(ResourceProviderTest
, ShutdownWithExportedResource
) {
2150 uint32 release_sync_point
= 0;
2151 bool lost_resource
= false;
2152 bool release_called
= false;
2153 uint32 sync_point
= 0;
2154 ResourceProvider::ResourceId resource
= CreateChildMailbox(
2155 &release_sync_point
, &lost_resource
, &release_called
, &sync_point
);
2157 // Transfer the resource, so we can't release it properly on shutdown.
2158 ResourceProvider::ResourceIdArray resource_ids_to_transfer
;
2159 resource_ids_to_transfer
.push_back(resource
);
2160 TransferableResourceArray list
;
2161 child_resource_provider_
->PrepareSendToParent(resource_ids_to_transfer
,
2164 EXPECT_EQ(0u, release_sync_point
);
2165 EXPECT_FALSE(lost_resource
);
2167 child_resource_provider_
.reset();
2169 // Since the resource is in the parent, the child considers it lost.
2170 EXPECT_EQ(0u, release_sync_point
);
2171 EXPECT_TRUE(lost_resource
);
2174 TEST_P(ResourceProviderTest
, LostContext
) {
2175 // TextureMailbox callbacks only exist for GL textures for now.
2176 if (GetParam() != ResourceProvider::GLTexture
)
2178 unsigned texture
= context()->createTexture();
2179 context()->bindTexture(GL_TEXTURE_2D
, texture
);
2180 gpu::Mailbox mailbox
;
2181 context()->genMailboxCHROMIUM(mailbox
.name
);
2182 context()->produceTextureCHROMIUM(GL_TEXTURE_2D
, mailbox
.name
);
2183 uint32 sync_point
= context()->insertSyncPoint();
2185 EXPECT_LT(0u, sync_point
);
2187 uint32 release_sync_point
= 0;
2188 bool lost_resource
= false;
2189 scoped_ptr
<SingleReleaseCallback
> callback
= SingleReleaseCallback::Create(
2190 base::Bind(ReleaseTextureMailbox
, &release_sync_point
, &lost_resource
));
2191 resource_provider_
->CreateResourceFromTextureMailbox(
2192 TextureMailbox(mailbox
, GL_TEXTURE_2D
, sync_point
), callback
.Pass());
2194 EXPECT_EQ(0u, release_sync_point
);
2195 EXPECT_FALSE(lost_resource
);
2197 resource_provider_
->DidLoseOutputSurface();
2198 resource_provider_
.reset();
2200 EXPECT_LE(sync_point
, release_sync_point
);
2201 EXPECT_TRUE(lost_resource
);
2204 TEST_P(ResourceProviderTest
, ScopedSampler
) {
2205 // Sampling is only supported for GL textures.
2206 if (GetParam() != ResourceProvider::GLTexture
)
2209 scoped_ptr
<TextureStateTrackingContext
> context_owned(
2210 new TextureStateTrackingContext
);
2211 TextureStateTrackingContext
* context
= context_owned
.get();
2213 FakeOutputSurfaceClient output_surface_client
;
2214 scoped_ptr
<OutputSurface
> output_surface(FakeOutputSurface::Create3d(
2215 context_owned
.PassAs
<TestWebGraphicsContext3D
>()));
2216 CHECK(output_surface
->BindToClient(&output_surface_client
));
2218 scoped_ptr
<ResourceProvider
> resource_provider(ResourceProvider::Create(
2219 output_surface
.get(), shared_bitmap_manager_
.get(), 0, false, 1));
2221 gfx::Size
size(1, 1);
2222 ResourceFormat format
= RGBA_8888
;
2225 ResourceProvider::ResourceId id
= resource_provider
->CreateResource(
2226 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureUsageAny
, format
);
2228 // Check that the texture gets created with the right sampler settings.
2229 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
))
2230 .Times(2); // Once to create and once to allocate.
2231 EXPECT_CALL(*context
,
2232 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
));
2233 EXPECT_CALL(*context
,
2234 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
));
2237 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
));
2240 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
));
2241 EXPECT_CALL(*context
,
2242 texParameteri(GL_TEXTURE_2D
,
2243 GL_TEXTURE_POOL_CHROMIUM
,
2244 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
));
2246 resource_provider
->AllocateForTesting(id
);
2247 Mock::VerifyAndClearExpectations(context
);
2249 // Creating a sampler with the default filter should not change any texture
2252 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
));
2253 ResourceProvider::ScopedSamplerGL
sampler(
2254 resource_provider
.get(), id
, GL_TEXTURE_2D
, GL_LINEAR
);
2255 Mock::VerifyAndClearExpectations(context
);
2258 // Using a different filter should be reflected in the texture parameters.
2260 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
));
2263 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
));
2266 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
));
2267 ResourceProvider::ScopedSamplerGL
sampler(
2268 resource_provider
.get(), id
, GL_TEXTURE_2D
, GL_NEAREST
);
2269 Mock::VerifyAndClearExpectations(context
);
2272 // Test resetting to the default filter.
2274 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
));
2275 EXPECT_CALL(*context
,
2276 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
));
2277 EXPECT_CALL(*context
,
2278 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
));
2279 ResourceProvider::ScopedSamplerGL
sampler(
2280 resource_provider
.get(), id
, GL_TEXTURE_2D
, GL_LINEAR
);
2281 Mock::VerifyAndClearExpectations(context
);
2285 TEST_P(ResourceProviderTest
, ManagedResource
) {
2286 // Sampling is only supported for GL textures.
2287 if (GetParam() != ResourceProvider::GLTexture
)
2290 scoped_ptr
<TextureStateTrackingContext
> context_owned(
2291 new TextureStateTrackingContext
);
2292 TextureStateTrackingContext
* context
= context_owned
.get();
2294 FakeOutputSurfaceClient output_surface_client
;
2295 scoped_ptr
<OutputSurface
> output_surface(FakeOutputSurface::Create3d(
2296 context_owned
.PassAs
<TestWebGraphicsContext3D
>()));
2297 CHECK(output_surface
->BindToClient(&output_surface_client
));
2299 scoped_ptr
<ResourceProvider
> resource_provider(ResourceProvider::Create(
2300 output_surface
.get(), shared_bitmap_manager_
.get(), 0, false, 1));
2302 gfx::Size
size(1, 1);
2303 ResourceFormat format
= RGBA_8888
;
2306 // Check that the texture gets created with the right sampler settings.
2307 ResourceProvider::ResourceId id
= resource_provider
->CreateManagedResource(
2311 ResourceProvider::TextureUsageAny
,
2313 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
));
2314 EXPECT_CALL(*context
,
2315 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
));
2316 EXPECT_CALL(*context
,
2317 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
));
2320 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
));
2323 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
));
2324 EXPECT_CALL(*context
,
2325 texParameteri(GL_TEXTURE_2D
,
2326 GL_TEXTURE_POOL_CHROMIUM
,
2327 GL_TEXTURE_POOL_MANAGED_CHROMIUM
));
2328 resource_provider
->CreateForTesting(id
);
2331 Mock::VerifyAndClearExpectations(context
);
2334 TEST_P(ResourceProviderTest
, TextureWrapMode
) {
2335 // Sampling is only supported for GL textures.
2336 if (GetParam() != ResourceProvider::GLTexture
)
2339 scoped_ptr
<TextureStateTrackingContext
> context_owned(
2340 new TextureStateTrackingContext
);
2341 TextureStateTrackingContext
* context
= context_owned
.get();
2343 FakeOutputSurfaceClient output_surface_client
;
2344 scoped_ptr
<OutputSurface
> output_surface(FakeOutputSurface::Create3d(
2345 context_owned
.PassAs
<TestWebGraphicsContext3D
>()));
2346 CHECK(output_surface
->BindToClient(&output_surface_client
));
2348 scoped_ptr
<ResourceProvider
> resource_provider(ResourceProvider::Create(
2349 output_surface
.get(), shared_bitmap_manager_
.get(), 0, false, 1));
2351 gfx::Size
size(1, 1);
2352 ResourceFormat format
= RGBA_8888
;
2353 GLenum texture_pool
= GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
;
2355 for (int texture_id
= 1; texture_id
<= 2; ++texture_id
) {
2356 GLint wrap_mode
= texture_id
== 1 ? GL_CLAMP_TO_EDGE
: GL_REPEAT
;
2357 // Check that the texture gets created with the right sampler settings.
2358 ResourceProvider::ResourceId id
=
2359 resource_provider
->CreateGLTexture(size
,
2363 ResourceProvider::TextureUsageAny
,
2365 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
));
2366 EXPECT_CALL(*context
,
2367 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
));
2368 EXPECT_CALL(*context
,
2369 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
));
2372 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, wrap_mode
));
2375 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, wrap_mode
));
2376 EXPECT_CALL(*context
,
2377 texParameteri(GL_TEXTURE_2D
,
2378 GL_TEXTURE_POOL_CHROMIUM
,
2379 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
));
2380 resource_provider
->CreateForTesting(id
);
2383 Mock::VerifyAndClearExpectations(context
);
2387 TEST_P(ResourceProviderTest
, TextureMailbox_SharedMemory
) {
2388 if (GetParam() != ResourceProvider::Bitmap
)
2391 gfx::Size
size(64, 64);
2392 const uint32_t kBadBeef
= 0xbadbeef;
2393 scoped_ptr
<base::SharedMemory
> shared_memory(
2394 CreateAndFillSharedMemory(size
, kBadBeef
));
2396 FakeOutputSurfaceClient output_surface_client
;
2397 scoped_ptr
<OutputSurface
> output_surface(
2398 FakeOutputSurface::CreateSoftware(make_scoped_ptr(
2399 new SoftwareOutputDevice
)));
2400 CHECK(output_surface
->BindToClient(&output_surface_client
));
2402 scoped_ptr
<ResourceProvider
> resource_provider(ResourceProvider::Create(
2403 output_surface
.get(), shared_bitmap_manager_
.get(), 0, false, 1));
2405 scoped_ptr
<SingleReleaseCallback
> callback
= SingleReleaseCallback::Create(
2406 base::Bind(&EmptyReleaseCallback
));
2407 TextureMailbox
mailbox(shared_memory
.get(), size
);
2409 ResourceProvider::ResourceId id
=
2410 resource_provider
->CreateResourceFromTextureMailbox(
2411 mailbox
, callback
.Pass());
2415 ResourceProvider::ScopedReadLockSoftware
lock(resource_provider
.get(), id
);
2416 const SkBitmap
* sk_bitmap
= lock
.sk_bitmap();
2417 EXPECT_EQ(sk_bitmap
->width(), size
.width());
2418 EXPECT_EQ(sk_bitmap
->height(), size
.height());
2419 EXPECT_EQ(*sk_bitmap
->getAddr32(16, 16), kBadBeef
);
2423 TEST_P(ResourceProviderTest
, TextureMailbox_GLTexture2D
) {
2424 // Mailboxing is only supported for GL textures.
2425 if (GetParam() != ResourceProvider::GLTexture
)
2428 scoped_ptr
<TextureStateTrackingContext
> context_owned(
2429 new TextureStateTrackingContext
);
2430 TextureStateTrackingContext
* context
= context_owned
.get();
2432 FakeOutputSurfaceClient output_surface_client
;
2433 scoped_ptr
<OutputSurface
> output_surface(FakeOutputSurface::Create3d(
2434 context_owned
.PassAs
<TestWebGraphicsContext3D
>()));
2435 CHECK(output_surface
->BindToClient(&output_surface_client
));
2437 scoped_ptr
<ResourceProvider
> resource_provider(ResourceProvider::Create(
2438 output_surface
.get(), shared_bitmap_manager_
.get(), 0, false, 1));
2440 unsigned texture_id
= 1;
2441 uint32 sync_point
= 30;
2442 unsigned target
= GL_TEXTURE_2D
;
2444 EXPECT_CALL(*context
, bindTexture(_
, _
)).Times(0);
2445 EXPECT_CALL(*context
, waitSyncPoint(_
)).Times(0);
2446 EXPECT_CALL(*context
, insertSyncPoint()).Times(0);
2447 EXPECT_CALL(*context
, produceTextureCHROMIUM(_
, _
)).Times(0);
2448 EXPECT_CALL(*context
, consumeTextureCHROMIUM(_
, _
)).Times(0);
2450 gpu::Mailbox gpu_mailbox
;
2451 memcpy(gpu_mailbox
.name
, "Hello world", strlen("Hello world") + 1);
2452 scoped_ptr
<SingleReleaseCallback
> callback
= SingleReleaseCallback::Create(
2453 base::Bind(&EmptyReleaseCallback
));
2455 TextureMailbox
mailbox(gpu_mailbox
, target
, sync_point
);
2457 ResourceProvider::ResourceId id
=
2458 resource_provider
->CreateResourceFromTextureMailbox(
2459 mailbox
, callback
.Pass());
2462 Mock::VerifyAndClearExpectations(context
);
2465 // Using the texture does a consume of the mailbox.
2466 EXPECT_CALL(*context
, bindTexture(target
, texture_id
));
2467 EXPECT_CALL(*context
, waitSyncPoint(sync_point
));
2468 EXPECT_CALL(*context
, consumeTextureCHROMIUM(target
, _
));
2470 EXPECT_CALL(*context
, insertSyncPoint()).Times(0);
2471 EXPECT_CALL(*context
, produceTextureCHROMIUM(_
, _
)).Times(0);
2473 ResourceProvider::ScopedReadLockGL
lock(resource_provider
.get(), id
);
2474 Mock::VerifyAndClearExpectations(context
);
2476 // When done with it, a sync point should be inserted, but no produce is
2478 EXPECT_CALL(*context
, bindTexture(_
, _
)).Times(0);
2479 EXPECT_CALL(*context
, insertSyncPoint());
2480 EXPECT_CALL(*context
, produceTextureCHROMIUM(_
, _
)).Times(0);
2482 EXPECT_CALL(*context
, waitSyncPoint(_
)).Times(0);
2483 EXPECT_CALL(*context
, consumeTextureCHROMIUM(_
, _
)).Times(0);
2487 TEST_P(ResourceProviderTest
, TextureMailbox_GLTextureExternalOES
) {
2488 // Mailboxing is only supported for GL textures.
2489 if (GetParam() != ResourceProvider::GLTexture
)
2492 scoped_ptr
<TextureStateTrackingContext
> context_owned(
2493 new TextureStateTrackingContext
);
2494 TextureStateTrackingContext
* context
= context_owned
.get();
2496 FakeOutputSurfaceClient output_surface_client
;
2497 scoped_ptr
<OutputSurface
> output_surface(FakeOutputSurface::Create3d(
2498 context_owned
.PassAs
<TestWebGraphicsContext3D
>()));
2499 CHECK(output_surface
->BindToClient(&output_surface_client
));
2501 scoped_ptr
<ResourceProvider
> resource_provider(ResourceProvider::Create(
2502 output_surface
.get(), shared_bitmap_manager_
.get(), 0, false, 1));
2504 unsigned texture_id
= 1;
2505 uint32 sync_point
= 30;
2506 unsigned target
= GL_TEXTURE_EXTERNAL_OES
;
2508 EXPECT_CALL(*context
, bindTexture(_
, _
)).Times(0);
2509 EXPECT_CALL(*context
, waitSyncPoint(_
)).Times(0);
2510 EXPECT_CALL(*context
, insertSyncPoint()).Times(0);
2511 EXPECT_CALL(*context
, produceTextureCHROMIUM(_
, _
)).Times(0);
2512 EXPECT_CALL(*context
, consumeTextureCHROMIUM(_
, _
)).Times(0);
2514 gpu::Mailbox gpu_mailbox
;
2515 memcpy(gpu_mailbox
.name
, "Hello world", strlen("Hello world") + 1);
2516 scoped_ptr
<SingleReleaseCallback
> callback
= SingleReleaseCallback::Create(
2517 base::Bind(&EmptyReleaseCallback
));
2519 TextureMailbox
mailbox(gpu_mailbox
, target
, sync_point
);
2521 ResourceProvider::ResourceId id
=
2522 resource_provider
->CreateResourceFromTextureMailbox(
2523 mailbox
, callback
.Pass());
2526 Mock::VerifyAndClearExpectations(context
);
2529 // Using the texture does a consume of the mailbox.
2530 EXPECT_CALL(*context
, bindTexture(target
, texture_id
));
2531 EXPECT_CALL(*context
, waitSyncPoint(sync_point
));
2532 EXPECT_CALL(*context
, consumeTextureCHROMIUM(target
, _
));
2534 EXPECT_CALL(*context
, insertSyncPoint()).Times(0);
2535 EXPECT_CALL(*context
, produceTextureCHROMIUM(_
, _
)).Times(0);
2537 ResourceProvider::ScopedReadLockGL
lock(resource_provider
.get(), id
);
2538 Mock::VerifyAndClearExpectations(context
);
2540 // When done with it, a sync point should be inserted, but no produce is
2542 EXPECT_CALL(*context
, bindTexture(_
, _
)).Times(0);
2543 EXPECT_CALL(*context
, insertSyncPoint());
2544 EXPECT_CALL(*context
, produceTextureCHROMIUM(_
, _
)).Times(0);
2546 EXPECT_CALL(*context
, waitSyncPoint(_
)).Times(0);
2547 EXPECT_CALL(*context
, consumeTextureCHROMIUM(_
, _
)).Times(0);
2551 class AllocationTrackingContext3D
: public TestWebGraphicsContext3D
{
2553 MOCK_METHOD0(NextTextureId
, GLuint());
2554 MOCK_METHOD1(RetireTextureId
, void(GLuint id
));
2555 MOCK_METHOD2(bindTexture
, void(GLenum target
, GLuint texture
));
2556 MOCK_METHOD5(texStorage2DEXT
,
2559 GLuint internalformat
,
2562 MOCK_METHOD9(texImage2D
,
2565 GLenum internalformat
,
2571 const void* pixels
));
2572 MOCK_METHOD9(texSubImage2D
,
2581 const void* pixels
));
2582 MOCK_METHOD9(asyncTexImage2DCHROMIUM
,
2585 GLenum internalformat
,
2591 const void* pixels
));
2592 MOCK_METHOD9(asyncTexSubImage2DCHROMIUM
,
2601 const void* pixels
));
2602 MOCK_METHOD8(compressedTexImage2D
,
2605 GLenum internalformat
,
2611 MOCK_METHOD1(waitAsyncTexImage2DCHROMIUM
, void(GLenum
));
2612 MOCK_METHOD3(createImageCHROMIUM
, GLuint(GLsizei
, GLsizei
, GLenum
));
2613 MOCK_METHOD1(destroyImageCHROMIUM
, void(GLuint
));
2614 MOCK_METHOD2(mapImageCHROMIUM
, void*(GLuint
, GLenum
));
2615 MOCK_METHOD3(getImageParameterivCHROMIUM
, void(GLuint
, GLenum
, GLint
*));
2616 MOCK_METHOD1(unmapImageCHROMIUM
, void(GLuint
));
2617 MOCK_METHOD2(bindTexImage2DCHROMIUM
, void(GLenum
, GLint
));
2618 MOCK_METHOD2(releaseTexImage2DCHROMIUM
, void(GLenum
, GLint
));
2620 // We're mocking bindTexture, so we override
2621 // TestWebGraphicsContext3D::texParameteri to avoid assertions related to the
2622 // currently bound texture.
2623 virtual void texParameteri(GLenum target
, GLenum pname
, GLint param
) {}
2626 TEST_P(ResourceProviderTest
, TextureAllocation
) {
2627 // Only for GL textures.
2628 if (GetParam() != ResourceProvider::GLTexture
)
2630 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
2631 new StrictMock
<AllocationTrackingContext3D
>);
2632 AllocationTrackingContext3D
* context
= context_owned
.get();
2634 FakeOutputSurfaceClient output_surface_client
;
2635 scoped_ptr
<OutputSurface
> output_surface(FakeOutputSurface::Create3d(
2636 context_owned
.PassAs
<TestWebGraphicsContext3D
>()));
2637 CHECK(output_surface
->BindToClient(&output_surface_client
));
2639 scoped_ptr
<ResourceProvider
> resource_provider(ResourceProvider::Create(
2640 output_surface
.get(), shared_bitmap_manager_
.get(), 0, false, 1));
2642 gfx::Size
size(2, 2);
2643 gfx::Vector2d
offset(0, 0);
2644 gfx::Rect
rect(0, 0, 2, 2);
2645 ResourceFormat format
= RGBA_8888
;
2646 ResourceProvider::ResourceId id
= 0;
2647 uint8_t pixels
[16] = { 0 };
2648 int texture_id
= 123;
2650 // Lazy allocation. Don't allocate when creating the resource.
2651 id
= resource_provider
->CreateResource(
2652 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureUsageAny
, format
);
2654 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
2655 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(1);
2656 resource_provider
->CreateForTesting(id
);
2658 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
2659 resource_provider
->DeleteResource(id
);
2661 Mock::VerifyAndClearExpectations(context
);
2663 // Do allocate when we set the pixels.
2664 id
= resource_provider
->CreateResource(
2665 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureUsageAny
, format
);
2667 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
2668 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(3);
2669 EXPECT_CALL(*context
, texImage2D(_
, _
, _
, 2, 2, _
, _
, _
, _
)).Times(1);
2670 EXPECT_CALL(*context
, texSubImage2D(_
, _
, _
, _
, 2, 2, _
, _
, _
)).Times(1);
2671 resource_provider
->SetPixels(id
, pixels
, rect
, rect
, offset
);
2673 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
2674 resource_provider
->DeleteResource(id
);
2676 Mock::VerifyAndClearExpectations(context
);
2678 // Same for async version.
2679 id
= resource_provider
->CreateResource(
2680 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureUsageAny
, format
);
2681 resource_provider
->AcquirePixelRasterBuffer(id
);
2683 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
2684 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(2);
2685 EXPECT_CALL(*context
, asyncTexImage2DCHROMIUM(_
, _
, _
, 2, 2, _
, _
, _
, _
))
2687 resource_provider
->BeginSetPixels(id
);
2688 ASSERT_TRUE(resource_provider
->DidSetPixelsComplete(id
));
2690 resource_provider
->ReleasePixelRasterBuffer(id
);
2692 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
2693 resource_provider
->DeleteResource(id
);
2695 Mock::VerifyAndClearExpectations(context
);
2698 TEST_P(ResourceProviderTest
, TextureAllocationStorageUsageAny
) {
2699 // Only for GL textures.
2700 if (GetParam() != ResourceProvider::GLTexture
)
2702 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
2703 new StrictMock
<AllocationTrackingContext3D
>);
2704 AllocationTrackingContext3D
* context
= context_owned
.get();
2705 context
->set_support_texture_storage(true);
2707 FakeOutputSurfaceClient output_surface_client
;
2708 scoped_ptr
<OutputSurface
> output_surface(FakeOutputSurface::Create3d(
2709 context_owned
.PassAs
<TestWebGraphicsContext3D
>()));
2710 CHECK(output_surface
->BindToClient(&output_surface_client
));
2712 scoped_ptr
<ResourceProvider
> resource_provider(ResourceProvider::Create(
2713 output_surface
.get(), shared_bitmap_manager_
.get(), 0, false, 1));
2715 gfx::Size
size(2, 2);
2716 ResourceFormat format
= RGBA_8888
;
2717 ResourceProvider::ResourceId id
= 0;
2718 int texture_id
= 123;
2720 // Lazy allocation. Don't allocate when creating the resource.
2721 id
= resource_provider
->CreateResource(
2722 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureUsageAny
, format
);
2724 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
2725 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(2);
2726 EXPECT_CALL(*context
, texStorage2DEXT(_
, _
, _
, 2, 2)).Times(1);
2727 resource_provider
->AllocateForTesting(id
);
2729 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
2730 resource_provider
->DeleteResource(id
);
2732 Mock::VerifyAndClearExpectations(context
);
2735 TEST_P(ResourceProviderTest
, TextureAllocationStorageUsageFramebuffer
) {
2736 // Only for GL textures.
2737 if (GetParam() != ResourceProvider::GLTexture
)
2739 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
2740 new StrictMock
<AllocationTrackingContext3D
>);
2741 AllocationTrackingContext3D
* context
= context_owned
.get();
2742 context
->set_support_texture_storage(true);
2744 FakeOutputSurfaceClient output_surface_client
;
2745 scoped_ptr
<OutputSurface
> output_surface(FakeOutputSurface::Create3d(
2746 context_owned
.PassAs
<TestWebGraphicsContext3D
>()));
2747 CHECK(output_surface
->BindToClient(&output_surface_client
));
2749 scoped_ptr
<ResourceProvider
> resource_provider(ResourceProvider::Create(
2750 output_surface
.get(), shared_bitmap_manager_
.get(), 0, false, 1));
2752 gfx::Size
size(2, 2);
2753 ResourceFormat format
= RGBA_8888
;
2754 ResourceProvider::ResourceId id
= 0;
2755 int texture_id
= 123;
2757 // Lazy allocation. Don't allocate when creating the resource.
2758 id
= resource_provider
->CreateResource(
2761 ResourceProvider::TextureUsageFramebuffer
,
2764 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
2765 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(2);
2766 EXPECT_CALL(*context
, texImage2D(_
, _
, _
, 2, 2, _
, _
, _
, _
)).Times(1);
2767 resource_provider
->AllocateForTesting(id
);
2769 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
2770 resource_provider
->DeleteResource(id
);
2772 Mock::VerifyAndClearExpectations(context
);
2775 TEST_P(ResourceProviderTest
, PixelBuffer_GLTexture
) {
2776 if (GetParam() != ResourceProvider::GLTexture
)
2778 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
2779 new StrictMock
<AllocationTrackingContext3D
>);
2780 AllocationTrackingContext3D
* context
= context_owned
.get();
2782 FakeOutputSurfaceClient output_surface_client
;
2783 scoped_ptr
<OutputSurface
> output_surface(FakeOutputSurface::Create3d(
2784 context_owned
.PassAs
<TestWebGraphicsContext3D
>()));
2785 CHECK(output_surface
->BindToClient(&output_surface_client
));
2787 gfx::Size
size(2, 2);
2788 ResourceFormat format
= RGBA_8888
;
2789 ResourceProvider::ResourceId id
= 0;
2790 int texture_id
= 123;
2792 scoped_ptr
<ResourceProvider
> resource_provider(ResourceProvider::Create(
2793 output_surface
.get(), shared_bitmap_manager_
.get(), 0, false, 1));
2795 id
= resource_provider
->CreateResource(
2796 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureUsageAny
, format
);
2797 resource_provider
->AcquirePixelRasterBuffer(id
);
2799 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
2800 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(2);
2801 EXPECT_CALL(*context
, asyncTexImage2DCHROMIUM(_
, _
, _
, 2, 2, _
, _
, _
, _
))
2803 resource_provider
->BeginSetPixels(id
);
2805 EXPECT_TRUE(resource_provider
->DidSetPixelsComplete(id
));
2807 resource_provider
->ReleasePixelRasterBuffer(id
);
2809 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
2810 resource_provider
->DeleteResource(id
);
2812 Mock::VerifyAndClearExpectations(context
);
2815 TEST_P(ResourceProviderTest
, ForcingAsyncUploadToComplete
) {
2816 // Only for GL textures.
2817 if (GetParam() != ResourceProvider::GLTexture
)
2819 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
2820 new StrictMock
<AllocationTrackingContext3D
>);
2821 AllocationTrackingContext3D
* context
= context_owned
.get();
2823 FakeOutputSurfaceClient output_surface_client
;
2824 scoped_ptr
<OutputSurface
> output_surface(FakeOutputSurface::Create3d(
2825 context_owned
.PassAs
<TestWebGraphicsContext3D
>()));
2826 CHECK(output_surface
->BindToClient(&output_surface_client
));
2828 gfx::Size
size(2, 2);
2829 ResourceFormat format
= RGBA_8888
;
2830 ResourceProvider::ResourceId id
= 0;
2831 int texture_id
= 123;
2833 scoped_ptr
<ResourceProvider
> resource_provider(ResourceProvider::Create(
2834 output_surface
.get(), shared_bitmap_manager_
.get(), 0, false, 1));
2836 id
= resource_provider
->CreateResource(
2837 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureUsageAny
, format
);
2838 resource_provider
->AcquirePixelRasterBuffer(id
);
2840 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
2841 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(2);
2842 EXPECT_CALL(*context
, asyncTexImage2DCHROMIUM(_
, _
, _
, 2, 2, _
, _
, _
, _
))
2844 resource_provider
->BeginSetPixels(id
);
2846 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(1);
2847 EXPECT_CALL(*context
, waitAsyncTexImage2DCHROMIUM(GL_TEXTURE_2D
)).Times(1);
2848 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, 0)).Times(1);
2849 resource_provider
->ForceSetPixelsToComplete(id
);
2851 resource_provider
->ReleasePixelRasterBuffer(id
);
2853 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
2854 resource_provider
->DeleteResource(id
);
2856 Mock::VerifyAndClearExpectations(context
);
2859 TEST_P(ResourceProviderTest
, PixelBufferLostContext
) {
2860 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
2861 new NiceMock
<AllocationTrackingContext3D
>);
2862 AllocationTrackingContext3D
* context
= context_owned
.get();
2864 FakeOutputSurfaceClient output_surface_client
;
2865 scoped_ptr
<OutputSurface
> output_surface(FakeOutputSurface::Create3d(
2866 context_owned
.PassAs
<TestWebGraphicsContext3D
>()));
2867 CHECK(output_surface
->BindToClient(&output_surface_client
));
2869 gfx::Size
size(2, 2);
2870 ResourceFormat format
= RGBA_8888
;
2871 ResourceProvider::ResourceId id
= 0;
2872 int texture_id
= 123;
2874 scoped_ptr
<ResourceProvider
> resource_provider(ResourceProvider::Create(
2875 output_surface
.get(), shared_bitmap_manager_
.get(), 0, false, 1));
2877 EXPECT_CALL(*context
, NextTextureId()).WillRepeatedly(Return(texture_id
));
2879 id
= resource_provider
->CreateResource(
2880 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureUsageAny
, format
);
2881 context
->loseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB
,
2882 GL_INNOCENT_CONTEXT_RESET_ARB
);
2884 resource_provider
->AcquirePixelRasterBuffer(id
);
2885 SkCanvas
* raster_canvas
= resource_provider
->MapPixelRasterBuffer(id
);
2886 EXPECT_TRUE(raster_canvas
== NULL
);
2887 resource_provider
->UnmapPixelRasterBuffer(id
);
2888 resource_provider
->ReleasePixelRasterBuffer(id
);
2889 Mock::VerifyAndClearExpectations(context
);
2892 TEST_P(ResourceProviderTest
, Image_GLTexture
) {
2893 // Only for GL textures.
2894 if (GetParam() != ResourceProvider::GLTexture
)
2896 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
2897 new StrictMock
<AllocationTrackingContext3D
>);
2898 AllocationTrackingContext3D
* context
= context_owned
.get();
2900 FakeOutputSurfaceClient output_surface_client
;
2901 scoped_ptr
<OutputSurface
> output_surface(FakeOutputSurface::Create3d(
2902 context_owned
.PassAs
<TestWebGraphicsContext3D
>()));
2903 CHECK(output_surface
->BindToClient(&output_surface_client
));
2905 const int kWidth
= 2;
2906 const int kHeight
= 2;
2907 gfx::Size
size(kWidth
, kHeight
);
2908 ResourceFormat format
= RGBA_8888
;
2909 ResourceProvider::ResourceId id
= 0;
2910 const unsigned kTextureId
= 123u;
2911 const unsigned kImageId
= 234u;
2913 scoped_ptr
<ResourceProvider
> resource_provider(ResourceProvider::Create(
2914 output_surface
.get(), shared_bitmap_manager_
.get(), 0, false, 1));
2916 id
= resource_provider
->CreateResource(
2917 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureUsageAny
, format
);
2919 const int kStride
= 4;
2920 void* dummy_mapped_buffer_address
= NULL
;
2921 EXPECT_CALL(*context
, createImageCHROMIUM(kWidth
, kHeight
, GL_RGBA8_OES
))
2922 .WillOnce(Return(kImageId
))
2923 .RetiresOnSaturation();
2924 EXPECT_CALL(*context
, getImageParameterivCHROMIUM(kImageId
,
2925 GL_IMAGE_ROWBYTES_CHROMIUM
,
2927 .WillOnce(SetArgPointee
<2>(kStride
))
2928 .RetiresOnSaturation();
2929 EXPECT_CALL(*context
, mapImageCHROMIUM(kImageId
, GL_READ_WRITE
))
2930 .WillOnce(Return(dummy_mapped_buffer_address
))
2931 .RetiresOnSaturation();
2932 resource_provider
->MapImageRasterBuffer(id
);
2934 EXPECT_CALL(*context
, unmapImageCHROMIUM(kImageId
))
2936 .RetiresOnSaturation();
2937 resource_provider
->UnmapImageRasterBuffer(id
);
2939 EXPECT_CALL(*context
, NextTextureId())
2940 .WillOnce(Return(kTextureId
))
2941 .RetiresOnSaturation();
2942 // Once in CreateTextureId and once in BindForSampling
2943 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, kTextureId
)).Times(2)
2944 .RetiresOnSaturation();
2945 EXPECT_CALL(*context
, bindTexImage2DCHROMIUM(GL_TEXTURE_2D
, kImageId
))
2947 .RetiresOnSaturation();
2949 ResourceProvider::ScopedSamplerGL
lock_gl(
2950 resource_provider
.get(), id
, GL_TEXTURE_2D
, GL_LINEAR
);
2951 EXPECT_EQ(kTextureId
, lock_gl
.texture_id());
2956 getImageParameterivCHROMIUM(kImageId
, GL_IMAGE_ROWBYTES_CHROMIUM
, _
))
2957 .WillOnce(SetArgPointee
<2>(kStride
))
2958 .RetiresOnSaturation();
2959 EXPECT_CALL(*context
, mapImageCHROMIUM(kImageId
, GL_READ_WRITE
))
2960 .WillOnce(Return(dummy_mapped_buffer_address
))
2961 .RetiresOnSaturation();
2962 resource_provider
->MapImageRasterBuffer(id
);
2964 EXPECT_CALL(*context
, unmapImageCHROMIUM(kImageId
))
2966 .RetiresOnSaturation();
2967 resource_provider
->UnmapImageRasterBuffer(id
);
2969 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, kTextureId
)).Times(1)
2970 .RetiresOnSaturation();
2971 EXPECT_CALL(*context
, releaseTexImage2DCHROMIUM(GL_TEXTURE_2D
, kImageId
))
2973 .RetiresOnSaturation();
2974 EXPECT_CALL(*context
, bindTexImage2DCHROMIUM(GL_TEXTURE_2D
, kImageId
))
2976 .RetiresOnSaturation();
2977 EXPECT_CALL(*context
, RetireTextureId(kTextureId
))
2979 .RetiresOnSaturation();
2981 ResourceProvider::ScopedSamplerGL
lock_gl(
2982 resource_provider
.get(), id
, GL_TEXTURE_2D
, GL_LINEAR
);
2983 EXPECT_EQ(kTextureId
, lock_gl
.texture_id());
2986 EXPECT_CALL(*context
, destroyImageCHROMIUM(kImageId
))
2988 .RetiresOnSaturation();
2991 TEST_P(ResourceProviderTest
, Image_Bitmap
) {
2992 if (GetParam() != ResourceProvider::Bitmap
)
2994 FakeOutputSurfaceClient output_surface_client
;
2995 scoped_ptr
<OutputSurface
> output_surface(
2996 FakeOutputSurface::CreateSoftware(make_scoped_ptr(
2997 new SoftwareOutputDevice
)));
2998 CHECK(output_surface
->BindToClient(&output_surface_client
));
3000 gfx::Size
size(1, 1);
3001 ResourceFormat format
= RGBA_8888
;
3002 ResourceProvider::ResourceId id
= 0;
3003 const uint32_t kBadBeef
= 0xbadbeef;
3005 scoped_ptr
<ResourceProvider
> resource_provider(ResourceProvider::Create(
3006 output_surface
.get(), shared_bitmap_manager_
.get(), 0, false, 1));
3008 id
= resource_provider
->CreateResource(
3009 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureUsageAny
, format
);
3012 bitmap
.allocN32Pixels(size
.width(), size
.height());
3013 *(bitmap
.getAddr32(0, 0)) = kBadBeef
;
3014 SkCanvas
* canvas
= resource_provider
->MapImageRasterBuffer(id
);
3015 ASSERT_TRUE(!!canvas
);
3016 canvas
->writePixels(bitmap
, 0, 0);
3017 resource_provider
->UnmapImageRasterBuffer(id
);
3020 ResourceProvider::ScopedReadLockSoftware
lock(resource_provider
.get(), id
);
3021 const SkBitmap
* sk_bitmap
= lock
.sk_bitmap();
3022 EXPECT_EQ(sk_bitmap
->width(), size
.width());
3023 EXPECT_EQ(sk_bitmap
->height(), size
.height());
3024 EXPECT_EQ(*sk_bitmap
->getAddr32(0, 0), kBadBeef
);
3027 resource_provider
->DeleteResource(id
);
3030 void InitializeGLAndCheck(ContextSharedData
* shared_data
,
3031 ResourceProvider
* resource_provider
,
3032 FakeOutputSurface
* output_surface
) {
3033 scoped_ptr
<ResourceProviderContext
> context_owned
=
3034 ResourceProviderContext::Create(shared_data
);
3035 ResourceProviderContext
* context
= context_owned
.get();
3037 scoped_refptr
<TestContextProvider
> context_provider
=
3038 TestContextProvider::Create(
3039 context_owned
.PassAs
<TestWebGraphicsContext3D
>());
3040 output_surface
->InitializeAndSetContext3d(context_provider
, NULL
);
3041 EXPECT_TRUE(resource_provider
->InitializeGL());
3043 CheckCreateResource(ResourceProvider::GLTexture
, resource_provider
, context
);
3046 TEST(ResourceProviderTest
, BasicInitializeGLSoftware
) {
3047 scoped_ptr
<ContextSharedData
> shared_data
= ContextSharedData::Create();
3048 FakeOutputSurfaceClient client
;
3049 scoped_ptr
<FakeOutputSurface
> output_surface(
3050 FakeOutputSurface::CreateDeferredGL(
3051 scoped_ptr
<SoftwareOutputDevice
>(new SoftwareOutputDevice
)));
3052 EXPECT_TRUE(output_surface
->BindToClient(&client
));
3053 scoped_ptr
<SharedBitmapManager
> shared_bitmap_manager(
3054 new TestSharedBitmapManager());
3055 scoped_ptr
<ResourceProvider
> resource_provider(ResourceProvider::Create(
3056 output_surface
.get(), shared_bitmap_manager
.get(), 0, false, 1));
3058 CheckCreateResource(ResourceProvider::Bitmap
, resource_provider
.get(), NULL
);
3060 InitializeGLAndCheck(shared_data
.get(),
3061 resource_provider
.get(),
3062 output_surface
.get());
3064 resource_provider
->InitializeSoftware();
3065 output_surface
->ReleaseGL();
3066 CheckCreateResource(ResourceProvider::Bitmap
, resource_provider
.get(), NULL
);
3068 InitializeGLAndCheck(shared_data
.get(),
3069 resource_provider
.get(),
3070 output_surface
.get());
3073 TEST_P(ResourceProviderTest
, CompressedTextureETC1Allocate
) {
3074 if (GetParam() != ResourceProvider::GLTexture
)
3077 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3078 new AllocationTrackingContext3D
);
3079 AllocationTrackingContext3D
* context
= context_owned
.get();
3080 context_owned
->set_support_compressed_texture_etc1(true);
3082 FakeOutputSurfaceClient output_surface_client
;
3083 scoped_ptr
<OutputSurface
> output_surface(FakeOutputSurface::Create3d(
3084 context_owned
.PassAs
<TestWebGraphicsContext3D
>()));
3085 CHECK(output_surface
->BindToClient(&output_surface_client
));
3087 gfx::Size
size(4, 4);
3088 scoped_ptr
<ResourceProvider
> resource_provider(
3089 ResourceProvider::Create(output_surface
.get(),
3090 shared_bitmap_manager_
.get(),
3094 int texture_id
= 123;
3096 ResourceProvider::ResourceId id
= resource_provider
->CreateResource(
3097 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureUsageAny
, ETC1
);
3099 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
3100 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(2);
3101 resource_provider
->AllocateForTesting(id
);
3103 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
3104 resource_provider
->DeleteResource(id
);
3107 TEST_P(ResourceProviderTest
, CompressedTextureETC1SetPixels
) {
3108 if (GetParam() != ResourceProvider::GLTexture
)
3111 scoped_ptr
<AllocationTrackingContext3D
> context_owned(
3112 new AllocationTrackingContext3D
);
3113 AllocationTrackingContext3D
* context
= context_owned
.get();
3114 context_owned
->set_support_compressed_texture_etc1(true);
3116 FakeOutputSurfaceClient output_surface_client
;
3117 scoped_ptr
<OutputSurface
> output_surface(FakeOutputSurface::Create3d(
3118 context_owned
.PassAs
<TestWebGraphicsContext3D
>()));
3119 CHECK(output_surface
->BindToClient(&output_surface_client
));
3121 gfx::Size
size(4, 4);
3122 scoped_ptr
<ResourceProvider
> resource_provider(
3123 ResourceProvider::Create(output_surface
.get(),
3124 shared_bitmap_manager_
.get(),
3128 int texture_id
= 123;
3131 ResourceProvider::ResourceId id
= resource_provider
->CreateResource(
3132 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureUsageAny
, ETC1
);
3134 EXPECT_CALL(*context
, NextTextureId()).WillOnce(Return(texture_id
));
3135 EXPECT_CALL(*context
, bindTexture(GL_TEXTURE_2D
, texture_id
)).Times(3);
3136 EXPECT_CALL(*context
,
3137 compressedTexImage2D(
3138 _
, 0, _
, size
.width(), size
.height(), _
, _
, _
)).Times(1);
3139 resource_provider
->SetPixels(
3140 id
, pixels
, gfx::Rect(size
), gfx::Rect(size
), gfx::Vector2d(0, 0));
3142 EXPECT_CALL(*context
, RetireTextureId(texture_id
)).Times(1);
3143 resource_provider
->DeleteResource(id
);
3146 INSTANTIATE_TEST_CASE_P(
3147 ResourceProviderTests
,
3148 ResourceProviderTest
,
3149 ::testing::Values(ResourceProvider::GLTexture
, ResourceProvider::Bitmap
));
3151 class TextureIdAllocationTrackingContext
: public TestWebGraphicsContext3D
{
3153 virtual GLuint
NextTextureId() OVERRIDE
{
3154 base::AutoLock
lock(namespace_
->lock
);
3155 return namespace_
->next_texture_id
++;
3157 virtual void RetireTextureId(GLuint
) OVERRIDE
{}
3158 GLuint
PeekTextureId() {
3159 base::AutoLock
lock(namespace_
->lock
);
3160 return namespace_
->next_texture_id
;
3164 TEST(ResourceProviderTest
, TextureAllocationChunkSize
) {
3165 scoped_ptr
<TextureIdAllocationTrackingContext
> context_owned(
3166 new TextureIdAllocationTrackingContext
);
3167 TextureIdAllocationTrackingContext
* context
= context_owned
.get();
3169 FakeOutputSurfaceClient output_surface_client
;
3170 scoped_ptr
<OutputSurface
> output_surface(FakeOutputSurface::Create3d(
3171 context_owned
.PassAs
<TestWebGraphicsContext3D
>()));
3172 CHECK(output_surface
->BindToClient(&output_surface_client
));
3173 scoped_ptr
<SharedBitmapManager
> shared_bitmap_manager(
3174 new TestSharedBitmapManager());
3176 gfx::Size
size(1, 1);
3177 ResourceFormat format
= RGBA_8888
;
3180 size_t kTextureAllocationChunkSize
= 1;
3181 scoped_ptr
<ResourceProvider
> resource_provider(
3182 ResourceProvider::Create(output_surface
.get(),
3183 shared_bitmap_manager
.get(),
3186 kTextureAllocationChunkSize
));
3188 ResourceProvider::ResourceId id
= resource_provider
->CreateResource(
3189 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureUsageAny
, format
);
3190 resource_provider
->AllocateForTesting(id
);
3191 Mock::VerifyAndClearExpectations(context
);
3193 DCHECK_EQ(2u, context
->PeekTextureId());
3194 resource_provider
->DeleteResource(id
);
3198 size_t kTextureAllocationChunkSize
= 8;
3199 scoped_ptr
<ResourceProvider
> resource_provider(
3200 ResourceProvider::Create(output_surface
.get(),
3201 shared_bitmap_manager
.get(),
3204 kTextureAllocationChunkSize
));
3206 ResourceProvider::ResourceId id
= resource_provider
->CreateResource(
3207 size
, GL_CLAMP_TO_EDGE
, ResourceProvider::TextureUsageAny
, format
);
3208 resource_provider
->AllocateForTesting(id
);
3209 Mock::VerifyAndClearExpectations(context
);
3211 DCHECK_EQ(10u, context
->PeekTextureId());
3212 resource_provider
->DeleteResource(id
);